9 Commits

Author SHA1 Message Date
cc409dc3f7 build: Let's build 0.0.25.
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 16m0s
2024-11-27 12:10:17 -05:00
af6091760c ssb+docs: prettier.
Some checks failed
Build Tilde Friends / Build-All (push) Has been cancelled
2024-11-27 12:07:00 -05:00
e1d93c003c docs: Update docs from wiki.
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 16m5s
2024-11-27 10:13:16 -05:00
ff9dd2dd03 haiku: Disable a bit of a test that is giving me an SQLITE_PROTOCOL error only on Haiku.
Some checks failed
Build Tilde Friends / Build-All (push) Has been cancelled
2024-11-27 15:05:23 -05:00
7a306bb3d2 build: Fix a regex warning.
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 16m11s
2024-11-27 14:36:50 -05:00
7ffc148358 build: I wanted to get the binary out of the makefile to appease F-Droid, and one thing lead to another.
Some checks failed
Build Tilde Friends / Build-All (push) Has been cancelled
2024-11-27 09:28:14 -05:00
50fef2edfa build: Fix on OpenBSD. TIL awk.
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 15m11s
2024-11-27 09:06:02 -05:00
aa40084010 build: Redid this thing in sed to make it work on more platforms.
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 15m16s
2024-11-26 22:55:01 -05:00
740d788c7c storage: Show accounts with the most follows, for help pruning accounts.
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 16m5s
2024-11-26 16:25:15 -05:00
9 changed files with 117 additions and 44 deletions

View File

@ -3,21 +3,21 @@
MAKEFLAGS += --warn-undefined-variables MAKEFLAGS += --warn-undefined-variables
MAKEFLAGS += --no-builtin-rules MAKEFLAGS += --no-builtin-rules
## == Tilde Friends makefile build. == ## == Tilde Friends build. ==
## ##
## This is a list of all supported build targets. ## This is a list of all supported build targets.
## ##
## Note: Consider passing -j$(nproc) or adding it to your $MAKEFLAGS to build ## Consider passing -j$(nproc) or adding it to your $MAKEFLAGS to build in
## in parallel (faster). ## parallel (faster).
## ##
## Useful variables to override: ## Useful variables to override:
## CC Compiler. ## CC := Compiler.
## AS Assembler. ## AS := Assembler.
## LD Linker. ## LD := Linker.
## ANDROID_SDK Path to the Android SDK. ## ANDROID_SDK := Path to the Android SDK.
VERSION_CODE := 30 VERSION_CODE := 30
VERSION_NUMBER := 0.0.25-wip VERSION_NUMBER := 0.0.25
VERSION_NAME := This program kills fascists. VERSION_NAME := This program kills fascists.
SQLITE_URL := https://www.sqlite.org/2024/sqlite-amalgamation-3470100.zip SQLITE_URL := https://www.sqlite.org/2024/sqlite-amalgamation-3470100.zip
@ -1245,12 +1245,22 @@ clean: ## Clean all generated files from the out/ directory.
## Documentation: ## Documentation:
## ##
help: ## Display this help message. help: ## Display this help message.
@gawk -vG=$$(tput setaf 2) -vR=$$(tput sgr0) ' \ @awk \
match($$0, "^(([^#:]*[^ :]) *:)?([^#]*)##([^#].+|)$$",a) { \ -F: \
if (a[2] != "") { printf " make %s%-22s%s %s\n", G, a[2], R, a[4]; next }\ -vG=$$(tput setaf 2) \
if (a[3] == "") { print a[4]; next }\ -vO=$$(tput setaf 3) \
printf "\n%-36s %s\n","",a[4]\ -vB=$$(tput setaf 4) \
}' $(filter-out %.d,$(MAKEFILE_LIST)) -vM=$$(tput setaf 5) \
-vC=$$(tput setaf 6) \
-vR=$$(tput sgr0) ' \
/^## ==.*==$$/ { sub(/^## ?/, ""); printf "%s%s%s\n", C, $$0, R } \
/^##.*:=.*/ { sub(/^## ?/, ""); sub(/:=/, ":"); printf " %s%-20s%s %s%s%s\n", M, $$1, R, O, $$2, R } \
/^##/ { sub(/^## ?/, ""); print $$0 } \
/^[[:alnum:]-]+:.*##/ { \
sub(/:.*##\s?/, ":"); \
printf " %s%-20s%s %s%s%s\n", G, $$1, R, O, $$2, R \
} \
' < $(filter-out %.d,$(MAKEFILE_LIST))
@echo "" # Blank line. @echo "" # Blank line.
.PHONY: help .PHONY: help
.DEFAULT_GOAL := help .DEFAULT_GOAL := help

View File

@ -408,9 +408,10 @@ ${JSON.stringify(mention, null, 2)}</pre
> >
<tf-user id=${self.message.author} .users=${self.users}></tf-user> <tf-user id=${self.message.author} .users=${self.users}></tf-user>
<span style="padding-right: 8px" <span style="padding-right: 8px"
><a tfarget="_top" href=${'#' + encodeURIComponent(self.message.id)}>%</a> ${new Date( ><a tfarget="_top" href=${'#' + encodeURIComponent(self.message.id)}
self.message.timestamp >%</a
).toLocaleString()}</span >
${new Date(self.message.timestamp).toLocaleString()}</span
> >
${raw_button} ${self.format == 'raw' ? self.render_raw() : inner} ${raw_button} ${self.format == 'raw' ? self.render_raw() : inner}
${self.render_votes()} ${self.render_votes()}
@ -449,7 +450,9 @@ ${JSON.stringify(mention, null, 2)}</pre
class="w3-card-4 w3-theme-d4 w3-border-theme" class="w3-card-4 w3-theme-d4 w3-border-theme"
style="margin-top: 8px; padding: 16px; overflow-wrap: anywhere" style="margin-top: 8px; padding: 16px; overflow-wrap: anywhere"
> >
<a target="_top" href=${'#' + encodeURIComponent(this.message.id)}>${this.message.id}</a> <a target="_top" href=${'#' + encodeURIComponent(this.message.id)}
>${this.message.id}</a
>
(placeholder) (placeholder)
<div>${this.render_votes()}</div> <div>${this.render_votes()}</div>
${(this.message.child_messages || []).map( ${(this.message.child_messages || []).map(
@ -600,7 +603,11 @@ ${JSON.stringify(content, null, 2)}</pre
${is_encrypted} ${is_encrypted}
<span style="flex: 1"></span> <span style="flex: 1"></span>
<span style="padding-right: 8px" <span style="padding-right: 8px"
><a target="_top" href=${'#' + encodeURIComponent(self.message.id)}>%</a> ><a
target="_top"
href=${'#' + encodeURIComponent(self.message.id)}
>%</a
>
${new Date(this.message.timestamp).toLocaleString()}</span ${new Date(this.message.timestamp).toLocaleString()}</span
> >
<span>${raw_button}</span> <span>${raw_button}</span>
@ -643,7 +650,11 @@ ${JSON.stringify(content, null, 2)}</pre
${is_encrypted} ${is_encrypted}
<span style="flex: 1"></span> <span style="flex: 1"></span>
<span style="padding-right: 8px" <span style="padding-right: 8px"
><a target="_top" href=${'#' + encodeURIComponent(self.message.id)}>%</a> ><a
target="_top"
href=${'#' + encodeURIComponent(self.message.id)}
>%</a
>
${new Date(this.message.timestamp).toLocaleString()}</span ${new Date(this.message.timestamp).toLocaleString()}</span
> >
<span>${raw_button}</span> <span>${raw_button}</span>
@ -733,7 +744,11 @@ ${JSON.stringify(content, null, 2)}</pre
<tf-user id=${this.message.author} .users=${this.users}></tf-user> <tf-user id=${this.message.author} .users=${this.users}></tf-user>
<span style="flex: 1"></span> <span style="flex: 1"></span>
<span style="padding-right: 8px" <span style="padding-right: 8px"
><a target="_top" href=${'#' + encodeURIComponent(self.message.id)}>%</a> ><a
target="_top"
href=${'#' + encodeURIComponent(self.message.id)}
>%</a
>
${new Date(this.message.timestamp).toLocaleString()}</span ${new Date(this.message.timestamp).toLocaleString()}</span
> >
<span>${raw_button}</span> <span>${raw_button}</span>

View File

@ -1,5 +1,5 @@
{ {
"type": "tildefriends-app", "type": "tildefriends-app",
"emoji": "💾", "emoji": "💾",
"previous": "&pAfoMT2ey5mk4X+ABcHQoliXPQaVaeolnTU6ri5P1UI=.sha256" "previous": "&mvGTlWKFR5QM/3nb4fJ2WQq0n/gNKvBmhGDkAvb8ki8=.sha256"
} }

View File

@ -1,10 +1,9 @@
async function query(sql, args) { async function query(sql, args) {
let rows = []; let rows = [];
await ssb.sqlAsync(sql, args ?? [], function (row) { await ssb.sqlAsync(sql, args ?? [], function (row) {
rows.push(row); rows.push(row);
}); });
return rows;; return rows;
} }
async function get_biggest() { async function get_biggest() {
@ -14,13 +13,16 @@ async function get_biggest() {
} }
async function get_total() { async function get_total() {
return (await query(` return (
await query(`
select sum(length(content)) as size, count(distinct author) as count from messages; select sum(length(content)) as size, count(distinct author) as count from messages;
`))[0]; `)
)[0];
} }
async function get_names(identities) { async function get_names(identities) {
return query(` return query(
`
SELECT author, name FROM ( SELECT author, name FROM (
SELECT SELECT
messages.author, messages.author,
@ -32,7 +34,20 @@ async function get_names(identities) {
json_extract(messages.content, '$.type') = 'about' AND json_extract(messages.content, '$.type') = 'about' AND
content ->> 'about' = messages.author AND name IS NOT NULL) content ->> 'about' = messages.author AND name IS NOT NULL)
WHERE author_rank = 1 WHERE author_rank = 1
`, [JSON.stringify(identities)]); `,
[JSON.stringify(identities)]
);
}
async function get_most_follows() {
return query(`
select author, count(*) as count
from messages
where content ->> 'type' = 'contact' and content ->> 'following' = true
group by author
order by count desc
limit 10;
`);
} }
function nice_size(bytes) { function nice_size(bytes) {
@ -47,24 +62,39 @@ function nice_size(bytes) {
} }
async function main() { async function main() {
await app.setDocument('<p style="color: #fff">Finding the top 10 largest feeds...</p>'); await app.setDocument(
'<p style="color: #fff">Finding the top 10 largest feeds...</p>'
);
let most_follows = await get_most_follows();
let total = await get_total(); let total = await get_total();
let identities = await ssb.getAllIdentities(); let identities = await ssb.getAllIdentities();
let following1 = await ssb.following(identities, 1); let following1 = await ssb.following(identities, 1);
let following2 = await ssb.following(identities, 2); let following2 = await ssb.following(identities, 2);
let biggest = await get_biggest(); let biggest = await get_biggest();
let names = await get_names(biggest.map(x => x.author)); let names = await get_names(
names = Object.fromEntries(names.map(x => [x.author, x.name])); [].concat(
biggest.map((x) => x.author),
most_follows.map((x) => x.author)
)
);
names = Object.fromEntries(names.map((x) => [x.author, x.name]));
for (let item of biggest) { for (let item of biggest) {
item.name = names[item.author]; item.name = names[item.author];
item.following = item.following =
identities.indexOf(item.author) != -1 ? 0 : identities.indexOf(item.author) != -1
following1[item.author] !== undefined ? 1 : ? 0
following2[item.author] !== undefined ? 2 : : following1[item.author] !== undefined
undefined; ? 1
: following2[item.author] !== undefined
? 2
: undefined;
}
for (let item of most_follows) {
item.name = names[item.author];
} }
let html = `<body style="color: #000; background-color: #ddd">\n let html = `<body style="color: #000; background-color: #ddd">\n
<h1>Top 10 Accounts by Size</h1> <h1>Storage Summary</h1>
<h2>Top 10 Accounts by Size</h2>
<ol>`; <ol>`;
for (let item of biggest) { for (let item of biggest) {
html += `<li> html += `<li>
@ -73,6 +103,18 @@ async function main() {
</li> </li>
\n`; \n`;
} }
html += `
</ol>
<h2>Top 10 Accounts by Follows</h2>
<ol>`;
for (let item of most_follows) {
html += `<li>
<span style="color: #888">${item.count}</span>
${following2[item.author] ? '✅' : '🚫'}
<a target="_top" href="/~core/ssb/#${encodeURI(item.author)}">${item.name ?? item.author}</a>
</li>
\n`;
}
html += ` html += `
</ol> </ol>
<p>Total <span style="color: #888">${nice_size(total.size)}</span> in ${total.count} accounts.</p> <p>Total <span style="color: #888">${nice_size(total.size)}</span> in ${total.count} accounts.</p>
@ -80,4 +122,6 @@ async function main() {
await app.setDocument(html); await app.setDocument(html);
} }
main().catch(function(e) { print(e); }); main().catch(function (e) {
print(e);
});

2
docs

Submodule docs updated: d14201ddcc...a40758cc4b

View File

@ -2,7 +2,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.unprompted.tildefriends" package="com.unprompted.tildefriends"
android:versionCode="30" android:versionCode="30"
android:versionName="0.0.25-wip"> android:versionName="0.0.25">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<application <application

View File

@ -874,9 +874,11 @@ static void _test_httpd(const tf_test_options_t* options)
uv_sleep(1000); uv_sleep(1000);
} }
#if !defined(__HAIKU__)
tf_ssb_t* ssb = tf_ssb_create(&loop, NULL, "file:out/test_db0.sqlite", NULL); tf_ssb_t* ssb = tf_ssb_create(&loop, NULL, "file:out/test_db0.sqlite", NULL);
const char* app_id = tf_ssb_db_get_property(ssb, "core", "path:test"); const char* app_id = tf_ssb_db_get_property(ssb, "core", "path:test");
tf_ssb_destroy(ssb); tf_ssb_destroy(ssb);
#endif
_http_check_status_code("http://localhost:8080/404", 404); _http_check_status_code("http://localhost:8080/404", 404);
_http_check_status_code("http://localhost:8080/", 303); _http_check_status_code("http://localhost:8080/", 303);
@ -889,6 +891,7 @@ static void _test_httpd(const tf_test_options_t* options)
_http_check_status_code("http://localhost:8080/~core/test/nonexistent.txt", 404); _http_check_status_code("http://localhost:8080/~core/test/nonexistent.txt", 404);
_http_check_body_contains("http://localhost:8080/&MV9b23bQeMQ7isAGTkoBZGErH853yGk0W/yUx1iU7dM=.sha256/view", "Hello, world!"); _http_check_body_contains("http://localhost:8080/&MV9b23bQeMQ7isAGTkoBZGErH853yGk0W/yUx1iU7dM=.sha256/view", "Hello, world!");
#if !defined(__HAIKU__)
char url[1024]; char url[1024];
snprintf(url, sizeof(url), "http://localhost:8080/%s/", app_id); snprintf(url, sizeof(url), "http://localhost:8080/%s/", app_id);
_http_check_body_contains(url, "<title>Tilde Friends</title>"); _http_check_body_contains(url, "<title>Tilde Friends</title>");
@ -897,6 +900,7 @@ static void _test_httpd(const tf_test_options_t* options)
snprintf(url, sizeof(url), "http://localhost:8080/%s/hello.txt", app_id); snprintf(url, sizeof(url), "http://localhost:8080/%s/hello.txt", app_id);
_http_check_body_contains(url, "Hello, world!"); _http_check_body_contains(url, "Hello, world!");
tf_free((void*)app_id); tf_free((void*)app_id);
#endif
uv_process_kill(&process, SIGTERM); uv_process_kill(&process, SIGTERM);
uv_close((uv_handle_t*)&process, NULL); uv_close((uv_handle_t*)&process, NULL);

View File

@ -1,2 +1,2 @@
#define VERSION_NUMBER "0.0.25-wip" #define VERSION_NUMBER "0.0.25"
#define VERSION_NAME "This program kills fascists." #define VERSION_NAME "This program kills fascists."