Compare commits
No commits in common. "main" and "v0.0.29" have entirely different histories.
@ -16,9 +16,9 @@ MAKEFLAGS += --no-builtin-rules
|
|||||||
## LD := Linker.
|
## LD := Linker.
|
||||||
## ANDROID_SDK := Path to the Android SDK.
|
## ANDROID_SDK := Path to the Android SDK.
|
||||||
|
|
||||||
VERSION_CODE := 35
|
VERSION_CODE := 34
|
||||||
VERSION_CODE_IOS := 12
|
VERSION_CODE_IOS := 11
|
||||||
VERSION_NUMBER := 0.0.30-wip
|
VERSION_NUMBER := 0.0.29
|
||||||
VERSION_NAME := This program kills fascists.
|
VERSION_NAME := This program kills fascists.
|
||||||
|
|
||||||
IPHONEOS_VERSION_MIN=14.0
|
IPHONEOS_VERSION_MIN=14.0
|
||||||
|
@ -38,7 +38,7 @@ dependencies in the right places.
|
|||||||
|
|
||||||
### Requirements
|
### Requirements
|
||||||
|
|
||||||
System OpenSSL libraries are assumed to be available on Haiku and OpenBSD.
|
System OpenSSL libraries are assumed to be available on Haiku and OpenSSL.
|
||||||
|
|
||||||
On MacOS, Xcode's command-line tools are expected to be available.
|
On MacOS, Xcode's command-line tools are expected to be available.
|
||||||
|
|
||||||
@ -55,8 +55,9 @@ standard.
|
|||||||
## Running
|
## Running
|
||||||
|
|
||||||
By default, running the built `out/debug/tildefriends` executable will start a
|
By default, running the built `out/debug/tildefriends` executable will start a
|
||||||
web server at <http://localhost:12345/>. `tildefriends -h` lists further
|
web server at <http://localhost:12345/>. It expects to be run with the
|
||||||
options.
|
repository root as the current working directory. `tildefriends -h` lists
|
||||||
|
further options.
|
||||||
|
|
||||||
The first user to create an account and log in will be granted administrative
|
The first user to create an account and log in will be granted administrative
|
||||||
privileges. Further administration can be done in the `admin` app at
|
privileges. Further administration can be done in the `admin` app at
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"type": "tildefriends-app",
|
"type": "tildefriends-app",
|
||||||
"emoji": "🦀",
|
"emoji": "🦀",
|
||||||
"previous": "&ErfmEIt3WboZp6PR3cC/i7XU/ZTI/2X5I9XvUN0GGMU=.sha256"
|
"previous": "&wOd/+1l5wpywBlfxC1Lm0i+HhYidrgSfrn9LRX7qy2w=.sha256"
|
||||||
}
|
}
|
||||||
|
@ -184,9 +184,9 @@ class TfElement extends LitElement {
|
|||||||
json_each(?1) AS following
|
json_each(?1) AS following
|
||||||
WHERE
|
WHERE
|
||||||
messages.author = following.value AND
|
messages.author = following.value AND
|
||||||
messages.content ->> 'type' = 'about' AND
|
|
||||||
messages.rowid > ?3 AND
|
messages.rowid > ?3 AND
|
||||||
messages.rowid <= ?4
|
messages.rowid <= ?4 AND
|
||||||
|
json_extract(messages.content, '$.type') = 'about'
|
||||||
UNION
|
UNION
|
||||||
SELECT
|
SELECT
|
||||||
messages.author, json(messages.content) AS content, messages.sequence
|
messages.author, json(messages.content) AS content, messages.sequence
|
||||||
@ -195,8 +195,8 @@ class TfElement extends LitElement {
|
|||||||
json_each(?2) AS following
|
json_each(?2) AS following
|
||||||
WHERE
|
WHERE
|
||||||
messages.author = following.value AND
|
messages.author = following.value AND
|
||||||
messages.content ->> 'type' = 'about' AND
|
messages.rowid <= ?4 AND
|
||||||
messages.rowid <= ?4
|
json_extract(messages.content, '$.type') = 'about'
|
||||||
ORDER BY messages.author, messages.sequence
|
ORDER BY messages.author, messages.sequence
|
||||||
`,
|
`,
|
||||||
[
|
[
|
||||||
@ -382,6 +382,7 @@ class TfElement extends LitElement {
|
|||||||
'🔐': latest[0],
|
'🔐': latest[0],
|
||||||
});
|
});
|
||||||
console.log('private took', (new Date() - start_time) / 1000.0);
|
console.log('private took', (new Date() - start_time) / 1000.0);
|
||||||
|
console.log(latest);
|
||||||
self.private_messages = latest[1];
|
self.private_messages = latest[1];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -371,53 +371,62 @@ class TfMessageElement extends LitElement {
|
|||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
copy_id(event) {
|
render_raw_button() {
|
||||||
navigator.clipboard.writeText(this.message?.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
render_menu() {
|
|
||||||
let content = this.get_content();
|
let content = this.get_content();
|
||||||
let formats = [['message', 'Message']];
|
let raw_button;
|
||||||
|
switch (this.format) {
|
||||||
|
case 'raw':
|
||||||
if (content?.type == 'post' || content?.type == 'blog') {
|
if (content?.type == 'post' || content?.type == 'blog') {
|
||||||
formats.push(['md', 'Markdown']);
|
raw_button = html`<button
|
||||||
|
class="w3-button w3-theme-d1"
|
||||||
|
@click=${() => (this.format = 'md')}
|
||||||
|
>
|
||||||
|
Markdown
|
||||||
|
</button>`;
|
||||||
|
} else {
|
||||||
|
raw_button = html`<button
|
||||||
|
class="w3-button w3-theme-d1"
|
||||||
|
@click=${() => (this.format = 'message')}
|
||||||
|
>
|
||||||
|
Message
|
||||||
|
</button>`;
|
||||||
}
|
}
|
||||||
if (this.message?.decrypted) {
|
break;
|
||||||
formats.push(['decrypted', 'Decrypted']);
|
case 'md':
|
||||||
|
raw_button = html`<button
|
||||||
|
class="w3-button w3-theme-d1"
|
||||||
|
@click=${() => (this.format = 'message')}
|
||||||
|
>
|
||||||
|
Message
|
||||||
|
</button>`;
|
||||||
|
break;
|
||||||
|
case 'decrypted':
|
||||||
|
raw_button = html`<button
|
||||||
|
class="w3-button w3-theme-d1"
|
||||||
|
@click=${() => (this.format = 'raw')}
|
||||||
|
>
|
||||||
|
Raw
|
||||||
|
</button>`;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (this.message.decrypted) {
|
||||||
|
raw_button = html`<button
|
||||||
|
class="w3-button w3-theme-d1"
|
||||||
|
@click=${() => (this.format = 'decrypted')}
|
||||||
|
>
|
||||||
|
Decrypted
|
||||||
|
</button>`;
|
||||||
|
} else {
|
||||||
|
raw_button = html`<button
|
||||||
|
class="w3-button w3-theme-d1"
|
||||||
|
@click=${() => (this.format = 'raw')}
|
||||||
|
>
|
||||||
|
Raw
|
||||||
|
</button>`;
|
||||||
}
|
}
|
||||||
formats.push(['raw', 'Raw']);
|
break;
|
||||||
return html`
|
}
|
||||||
<div class="w3-bar-item w3-right w3-dropdown-hover">
|
return raw_button;
|
||||||
<button class="w3-button w3-theme-d1">%</button>
|
|
||||||
<div
|
|
||||||
class="w3-dropdown-content w3-bar-block w3-card-4 w3-theme-l1"
|
|
||||||
style="right: 48px"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
target="_top"
|
|
||||||
class="w3-button w3-bar-item"
|
|
||||||
href=${'#' + encodeURIComponent(this.message?.id)}
|
|
||||||
>${this.message?.id}</a
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
class="w3-button w3-bar-item w3-border-bottom"
|
|
||||||
@click=${this.copy_id}
|
|
||||||
>
|
|
||||||
Copy ID
|
|
||||||
</button>
|
|
||||||
${formats.map(
|
|
||||||
([format, name]) => html`
|
|
||||||
<button
|
|
||||||
class="w3-button w3-bar-item"
|
|
||||||
style=${format == this.format ? 'font-weight: bold' : ''}
|
|
||||||
@click=${() => (this.format = format)}
|
|
||||||
>
|
|
||||||
${name}
|
|
||||||
</button>
|
|
||||||
`
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render_header() {
|
render_header() {
|
||||||
@ -431,10 +440,14 @@ class TfMessageElement extends LitElement {
|
|||||||
<span class="w3-bar-item">
|
<span class="w3-bar-item">
|
||||||
<tf-user id=${this.message.author} .users=${this.users}></tf-user>
|
<tf-user id=${this.message.author} .users=${this.users}></tf-user>
|
||||||
</span>
|
</span>
|
||||||
${is_encrypted} ${this.render_menu()}
|
${is_encrypted}
|
||||||
<div class="w3-bar-item w3-right" style="text-wrap: nowrap">
|
<span class="w3-bar-item w3-right">${this.render_raw_button()}</span>
|
||||||
${new Date(this.message.timestamp).toLocaleString()}
|
<span class="w3-bar-item w3-right" style="text-wrap: nowrap"
|
||||||
</div>
|
><a target="_top" href=${'#' + encodeURIComponent(this.message.id)}
|
||||||
|
>%</a
|
||||||
|
>
|
||||||
|
${new Date(this.message.timestamp).toLocaleString()}</span
|
||||||
|
>
|
||||||
</header>
|
</header>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
@ -159,7 +159,6 @@ class TfTabNewsFeedElement extends LitElement {
|
|||||||
);
|
);
|
||||||
result = (await this.decrypt(result)).filter((x) => x.decrypted);
|
result = (await this.decrypt(result)).filter((x) => x.decrypted);
|
||||||
} else {
|
} else {
|
||||||
let t0 = new Date();
|
|
||||||
result = await tfrpc.rpc.query(
|
result = await tfrpc.rpc.query(
|
||||||
`
|
`
|
||||||
WITH
|
WITH
|
||||||
@ -167,45 +166,26 @@ class TfTabNewsFeedElement extends LitElement {
|
|||||||
SELECT messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
SELECT messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
||||||
FROM messages
|
FROM messages
|
||||||
JOIN json_each(?) AS following ON messages.author = following.value
|
JOIN json_each(?) AS following ON messages.author = following.value
|
||||||
),
|
WHERE timestamp >= 0 AND timestamp < ?3),
|
||||||
news AS (
|
news AS (
|
||||||
SELECT * FROM all_news
|
SELECT * FROM all_news
|
||||||
WHERE all_news.timestamp < ?3 AND (?2 IS NULL OR all_news.timestamp >= ?2)
|
WHERE (?2 IS NULL OR all_news.timestamp >= ?2) AND all_news.timestamp < ?3
|
||||||
ORDER BY timestamp DESC LIMIT 20
|
ORDER BY timestamp DESC LIMIT 20
|
||||||
)
|
)
|
||||||
|
SELECT FALSE AS is_primary, messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
||||||
|
FROM news
|
||||||
|
JOIN messages_refs ON news.id = messages_refs.ref
|
||||||
|
JOIN messages ON messages_refs.message = messages.id
|
||||||
|
UNION
|
||||||
|
SELECT FALSE AS is_primary, messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
||||||
|
FROM news
|
||||||
|
JOIN messages_refs ON news.id = messages_refs.message
|
||||||
|
JOIN messages ON messages_refs.ref = messages.id
|
||||||
|
UNION
|
||||||
SELECT TRUE AS is_primary, news.* FROM news
|
SELECT TRUE AS is_primary, news.* FROM news
|
||||||
`,
|
`,
|
||||||
[JSON.stringify(this.following), start_time, end_time]
|
[JSON.stringify(this.following), start_time, end_time]
|
||||||
);
|
);
|
||||||
let news_length = result.length;
|
|
||||||
let t1 = new Date();
|
|
||||||
let refs = await tfrpc.rpc.query(
|
|
||||||
`
|
|
||||||
WITH
|
|
||||||
news AS (
|
|
||||||
SELECT value AS id FROM json_each(?)
|
|
||||||
)
|
|
||||||
SELECT refs_out.ref AS ref FROM messages_refs refs_out JOIN news ON refs_out.message = news.id
|
|
||||||
UNION
|
|
||||||
SELECT refs_in.message AS ref FROM messages_refs refs_in JOIN news ON refs_in.ref = news.id
|
|
||||||
`,
|
|
||||||
[JSON.stringify(result.map((x) => x.id))]
|
|
||||||
);
|
|
||||||
let t2 = new Date();
|
|
||||||
let related_messages = await tfrpc.rpc.query(
|
|
||||||
`
|
|
||||||
SELECT FALSE AS is_primary, messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
|
||||||
FROM messages
|
|
||||||
JOIN json_each(?2) refs ON messages.id = refs.value
|
|
||||||
JOIN json_each(?1) AS following ON messages.author = following.value
|
|
||||||
`,
|
|
||||||
[JSON.stringify(this.following), JSON.stringify(refs.map((x) => x.ref))]
|
|
||||||
);
|
|
||||||
result = [].concat(result, related_messages);
|
|
||||||
let t3 = new Date();
|
|
||||||
console.log(
|
|
||||||
`load of ${result.length} rows took ${(t3 - t0) / 1000} (${(t1 - t0) / 1000} to find ${news_length} messages, ${(t2 - t1) / 1000} to find ${refs.length} refs, and ${(t3 - t2) / 1000} to find ${related_messages.length} related messages) following=${this.following.length} st=${start_time} et=${end_time}`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
this.time_loading = undefined;
|
this.time_loading = undefined;
|
||||||
return result;
|
return result;
|
||||||
@ -331,7 +311,7 @@ class TfTabNewsFeedElement extends LitElement {
|
|||||||
this.messages = this.merge_messages(this.messages, messages);
|
this.messages = this.merge_messages(this.messages, messages);
|
||||||
this.time_loading = undefined;
|
this.time_loading = undefined;
|
||||||
console.log(
|
console.log(
|
||||||
`loading ${messages.length} messages done for ${self.whoami} in ${(new Date() - start_time) / 1000}s`
|
`loading messages done for ${self.whoami} in ${(new Date() - start_time) / 1000}s`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,7 +285,7 @@ class TfTabNewsElement extends LitElement {
|
|||||||
return cache(html`
|
return cache(html`
|
||||||
${this.render_sidebar()}
|
${this.render_sidebar()}
|
||||||
<div
|
<div
|
||||||
style="margin-left: 2in; padding: 0px; top: 0; max-height: 100%; overflow: auto; contain: layout"
|
style="margin-left: 2in; padding: 0px; top: 0; max-height: 100%; overflow: auto"
|
||||||
id="main"
|
id="main"
|
||||||
class="w3-main"
|
class="w3-main"
|
||||||
>
|
>
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"type": "tildefriends-app",
|
|
||||||
"emoji": "🕸",
|
|
||||||
"previous": "&n7hu5b8/TsfiG6FDlCRG5nPCrIdCr96+xpIJ/aQT/uM=.sha256"
|
|
||||||
}
|
|
100
apps/web/app.js
100
apps/web/app.js
@ -1,100 +0,0 @@
|
|||||||
let g_hash;
|
|
||||||
|
|
||||||
async function query(sql, params) {
|
|
||||||
let results = [];
|
|
||||||
await ssb.sqlAsync(sql, params, function (row) {
|
|
||||||
results.push(row);
|
|
||||||
});
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function resolve(id) {
|
|
||||||
try {
|
|
||||||
let blob = await ssb.blobGet(id);
|
|
||||||
if (blob) {
|
|
||||||
let json;
|
|
||||||
try {
|
|
||||||
json = JSON.parse(utf8Decode(blob));
|
|
||||||
} catch {
|
|
||||||
return {id: utf8Decode(blob)};
|
|
||||||
}
|
|
||||||
if (json?.links) {
|
|
||||||
for (let [key, value] of Object.entries(json.links)) {
|
|
||||||
json.links[key] = await resolve(value);
|
|
||||||
}
|
|
||||||
return json;
|
|
||||||
} else {
|
|
||||||
return 'huh?' + json;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return `missing<${id}>`;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
return id + ': ' + e.message;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function get_names(identities) {
|
|
||||||
return Object.fromEntries(
|
|
||||||
(
|
|
||||||
await query(
|
|
||||||
`
|
|
||||||
SELECT author, name FROM (
|
|
||||||
SELECT
|
|
||||||
messages.author,
|
|
||||||
RANK() OVER (PARTITION BY messages.author ORDER BY messages.sequence DESC) AS author_rank,
|
|
||||||
messages.content ->> 'name' AS name
|
|
||||||
FROM messages
|
|
||||||
JOIN json_each(?) AS identities ON identities.value = messages.author
|
|
||||||
WHERE
|
|
||||||
json_extract(messages.content, '$.type') = 'about' AND
|
|
||||||
content ->> 'about' = messages.author AND name IS NOT NULL)
|
|
||||||
WHERE author_rank = 1
|
|
||||||
`,
|
|
||||||
[JSON.stringify(identities)]
|
|
||||||
)
|
|
||||||
).map((x) => [x.author, x.name])
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function render(hash) {
|
|
||||||
g_hash = hash;
|
|
||||||
if (!hash) {
|
|
||||||
let sites = await query(
|
|
||||||
`
|
|
||||||
SELECT site.author, site.id
|
|
||||||
FROM messages site
|
|
||||||
WHERE site.content ->> 'type' = 'web-init'
|
|
||||||
`,
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
let names = await get_names(sites.map((x) => x.author));
|
|
||||||
if (hash === g_hash) {
|
|
||||||
await app.setDocument(
|
|
||||||
`<ul style="background-color: #ddd">${sites.map((x) => `<li><a target="_top" href="#${encodeURIComponent(x.id)}">${names[x.author] ?? x.author} - ${x.id}</a></li>`).join('\n')}</ul>`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let site_id =
|
|
||||||
hash.charAt(0) == '#'
|
|
||||||
? decodeURIComponent(hash.substring(1))
|
|
||||||
: decodeURIComponent(hash);
|
|
||||||
await app.setDocument(`<html style="margin: 0; padding: 0; width: 100vw; height: 100vh; margin: 0; padding: 0">
|
|
||||||
<body style="display: flex; flex-direction: column; width: 100vw; height: 100vh">
|
|
||||||
<iframe src="${encodeURIComponent(site_id)}/index.html" style="flex: 1 1; border: 0; background-color: #fff"></iframe>
|
|
||||||
</body>
|
|
||||||
</html>`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
core.register('message', async function message_handler(message) {
|
|
||||||
if (message.event == 'hashChange') {
|
|
||||||
await render(message.hash);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
async function main() {
|
|
||||||
render(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
main();
|
|
@ -1,63 +0,0 @@
|
|||||||
async function query(sql, params) {
|
|
||||||
let results = [];
|
|
||||||
await ssb.sqlAsync(sql, params, function (row) {
|
|
||||||
results.push(row);
|
|
||||||
});
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
function guess_content_type(name) {
|
|
||||||
if (name.endsWith('.html')) {
|
|
||||||
return 'text/html; charset=UTF-8';
|
|
||||||
} else if (name.endsWith('.js') || name.endsWith('.mjs')) {
|
|
||||||
return 'text/javascript; charset=UTF-8';
|
|
||||||
} else if (name.endsWith('.css')) {
|
|
||||||
return 'text/stylesheet; charset=UTF-8';
|
|
||||||
} else {
|
|
||||||
return 'application/binary';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function main() {
|
|
||||||
let path = request.path.replaceAll(/(%[0-9a-fA-F]{2})/g, (x) =>
|
|
||||||
String.fromCharCode(parseInt(x.substring(1), 16))
|
|
||||||
);
|
|
||||||
let match = path.match(/^(%.{44}\.sha256)(?:\/)?(.*)$/);
|
|
||||||
|
|
||||||
let content_type = guess_content_type(request.path);
|
|
||||||
let root = await query(
|
|
||||||
`
|
|
||||||
SELECT root.content ->> 'root' AS root
|
|
||||||
FROM messages site
|
|
||||||
JOIN messages root
|
|
||||||
ON site.id = ? AND root.author = site.author AND root.content ->> 'site' = site.id
|
|
||||||
ORDER BY root.sequence DESC LIMIT 1
|
|
||||||
`,
|
|
||||||
[match[1]]
|
|
||||||
);
|
|
||||||
let root_id = root[0]['root'];
|
|
||||||
let last_id = root_id;
|
|
||||||
let blob = await ssb.blobGet(root_id);
|
|
||||||
try {
|
|
||||||
for (let part of match[2]?.split('/')) {
|
|
||||||
let dir = JSON.parse(utf8Decode(blob));
|
|
||||||
last_id = dir?.links[part];
|
|
||||||
blob = await ssb.blobGet(dir?.links[part]);
|
|
||||||
content_type = guess_content_type(part);
|
|
||||||
}
|
|
||||||
} catch {}
|
|
||||||
|
|
||||||
respond({
|
|
||||||
status_code: 200,
|
|
||||||
data: blob ? utf8Decode(blob) : `${last_id} not found`,
|
|
||||||
content_type: content_type,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
main().catch(function (e) {
|
|
||||||
respond({
|
|
||||||
status_code: 200,
|
|
||||||
data: `${e.message}\n${e.stack}`,
|
|
||||||
content_type: 'text/plain',
|
|
||||||
});
|
|
||||||
});
|
|
@ -25,14 +25,14 @@
|
|||||||
}:
|
}:
|
||||||
pkgs.stdenv.mkDerivation rec {
|
pkgs.stdenv.mkDerivation rec {
|
||||||
pname = "tildefriends";
|
pname = "tildefriends";
|
||||||
version = "0.0.29";
|
version = "0.0.28";
|
||||||
|
|
||||||
src = pkgs.fetchFromGitea {
|
src = pkgs.fetchFromGitea {
|
||||||
domain = "dev.tildefriends.net";
|
domain = "dev.tildefriends.net";
|
||||||
owner = "cory";
|
owner = "cory";
|
||||||
repo = "tildefriends";
|
repo = "tildefriends";
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
hash = "sha256-bQXFpocOYOlFmVj9OZeQhNrgFuTJ8sx2RSw1tgmelOM=";
|
hash = "sha256-vcLJCXgIrjC37t9oavK2QMRcMJljghuzKDYxQ4nyTcE=";
|
||||||
fetchSubmodules = true;
|
fetchSubmodules = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
2
deps/codemirror/cm6.js
vendored
2
deps/codemirror/cm6.js
vendored
File diff suppressed because one or more lines are too long
200
deps/codemirror_src/package-lock.json
generated
vendored
200
deps/codemirror_src/package-lock.json
generated
vendored
@ -92,9 +92,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@codemirror/language": {
|
"node_modules/@codemirror/language": {
|
||||||
"version": "6.11.0",
|
"version": "6.10.8",
|
||||||
"resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.11.0.tgz",
|
"resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.10.8.tgz",
|
||||||
"integrity": "sha512-A7+f++LodNNc1wGgoRDTt78cOwWm9KVezApgjOMp1W4hM0898nsqBXwF+sbePE7ZRcjN7Sa1Z5m2oN27XkmEjQ==",
|
"integrity": "sha512-wcP8XPPhDH2vTqf181U8MbZnW+tDyPYy0UzVOa+oHORjyT+mhhom9vBd7dApJwoDz9Nb/a8kHjJIsuA/t8vNFw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/state": "^6.0.0",
|
"@codemirror/state": "^6.0.0",
|
||||||
"@codemirror/view": "^6.23.0",
|
"@codemirror/view": "^6.23.0",
|
||||||
@ -105,9 +105,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@codemirror/lint": {
|
"node_modules/@codemirror/lint": {
|
||||||
"version": "6.8.5",
|
"version": "6.8.4",
|
||||||
"resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.8.5.tgz",
|
"resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.8.4.tgz",
|
||||||
"integrity": "sha512-s3n3KisH7dx3vsoeGMxsbRAgKe4O1vbrnKBClm99PU0fWxmxsx5rR2PfqQgIt+2MMJBHbiJ5rfIdLYfB9NNvsA==",
|
"integrity": "sha512-u4q7PnZlJUojeRe8FJa/njJcMctISGgPQ4PnWsd9268R4ZTtU+tfFYmwkBvgcrK2+QQ8tYFVALVb5fVJykKc5A==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/state": "^6.0.0",
|
"@codemirror/state": "^6.0.0",
|
||||||
"@codemirror/view": "^6.35.0",
|
"@codemirror/view": "^6.35.0",
|
||||||
@ -217,9 +217,9 @@
|
|||||||
"integrity": "sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA=="
|
"integrity": "sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA=="
|
||||||
},
|
},
|
||||||
"node_modules/@lezer/css": {
|
"node_modules/@lezer/css": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.10",
|
||||||
"resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.1.10.tgz",
|
||||||
"integrity": "sha512-FuAnusbLBl1SEAtfN8NdShxYJiESKw9LAFysfea1T96jD3ydBn12oYjaSG1a04BQRIUd93/0D8e5CV1cUMkmQg==",
|
"integrity": "sha512-V5/89eDapjeAkWPBpWEfQjZ1Hag3aYUUJOL8213X0dFRuXJ4BXa5NKl9USzOnaLod4AOpmVCkduir2oKwZYZtg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@lezer/common": "^1.2.0",
|
"@lezer/common": "^1.2.0",
|
||||||
"@lezer/highlight": "^1.0.0",
|
"@lezer/highlight": "^1.0.0",
|
||||||
@ -344,9 +344,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||||
"version": "4.37.0",
|
"version": "4.34.9",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.37.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.9.tgz",
|
||||||
"integrity": "sha512-l7StVw6WAa8l3vA1ov80jyetOAEo1FtHvZDbzXDO/02Sq/QVvqlHkYoFwDJPIMj0GKiistsBudfx5tGFnwYWDQ==",
|
"integrity": "sha512-qZdlImWXur0CFakn2BJ2znJOdqYZKiedEPEVNTBrpfPjc/YuTGcaYZcdmNFTkUj3DU0ZM/AElcM8Ybww3xVLzA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@ -356,9 +356,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-android-arm64": {
|
"node_modules/@rollup/rollup-android-arm64": {
|
||||||
"version": "4.37.0",
|
"version": "4.34.9",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.37.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.9.tgz",
|
||||||
"integrity": "sha512-6U3SlVyMxezt8Y+/iEBcbp945uZjJwjZimu76xoG7tO1av9VO691z8PkhzQ85ith2I8R2RddEPeSfcbyPfD4hA==",
|
"integrity": "sha512-4KW7P53h6HtJf5Y608T1ISKvNIYLWRKMvfnG0c44M6In4DQVU58HZFEVhWINDZKp7FZps98G3gxwC1sb0wXUUg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -368,9 +368,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||||
"version": "4.37.0",
|
"version": "4.34.9",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.37.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.9.tgz",
|
||||||
"integrity": "sha512-+iTQ5YHuGmPt10NTzEyMPbayiNTcOZDWsbxZYR1ZnmLnZxG17ivrPSWFO9j6GalY0+gV3Jtwrrs12DBscxnlYA==",
|
"integrity": "sha512-0CY3/K54slrzLDjOA7TOjN1NuLKERBgk9nY5V34mhmuu673YNb+7ghaDUs6N0ujXR7fz5XaS5Aa6d2TNxZd0OQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -380,9 +380,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-darwin-x64": {
|
"node_modules/@rollup/rollup-darwin-x64": {
|
||||||
"version": "4.37.0",
|
"version": "4.34.9",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.37.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.9.tgz",
|
||||||
"integrity": "sha512-m8W2UbxLDcmRKVjgl5J/k4B8d7qX2EcJve3Sut7YGrQoPtCIQGPH5AMzuFvYRWZi0FVS0zEY4c8uttPfX6bwYQ==",
|
"integrity": "sha512-eOojSEAi/acnsJVYRxnMkPFqcxSMFfrw7r2iD9Q32SGkb/Q9FpUY1UlAu1DH9T7j++gZ0lHjnm4OyH2vCI7l7Q==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -392,9 +392,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-freebsd-arm64": {
|
"node_modules/@rollup/rollup-freebsd-arm64": {
|
||||||
"version": "4.37.0",
|
"version": "4.34.9",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.37.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.9.tgz",
|
||||||
"integrity": "sha512-FOMXGmH15OmtQWEt174v9P1JqqhlgYge/bUjIbiVD1nI1NeJ30HYT9SJlZMqdo1uQFyt9cz748F1BHghWaDnVA==",
|
"integrity": "sha512-2lzjQPJbN5UnHm7bHIUKFMulGTQwdvOkouJDpPysJS+QFBGDJqcfh+CxxtG23Ik/9tEvnebQiylYoazFMAgrYw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -404,9 +404,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-freebsd-x64": {
|
"node_modules/@rollup/rollup-freebsd-x64": {
|
||||||
"version": "4.37.0",
|
"version": "4.34.9",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.37.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.9.tgz",
|
||||||
"integrity": "sha512-SZMxNttjPKvV14Hjck5t70xS3l63sbVwl98g3FlVVx2YIDmfUIy29jQrsw06ewEYQ8lQSuY9mpAPlmgRD2iSsA==",
|
"integrity": "sha512-SLl0hi2Ah2H7xQYd6Qaiu01kFPzQ+hqvdYSoOtHYg/zCIFs6t8sV95kaoqjzjFwuYQLtOI0RZre/Ke0nPaQV+g==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -416,9 +416,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||||
"version": "4.37.0",
|
"version": "4.34.9",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.37.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.9.tgz",
|
||||||
"integrity": "sha512-hhAALKJPidCwZcj+g+iN+38SIOkhK2a9bqtJR+EtyxrKKSt1ynCBeqrQy31z0oWU6thRZzdx53hVgEbRkuI19w==",
|
"integrity": "sha512-88I+D3TeKItrw+Y/2ud4Tw0+3CxQ2kLgu3QvrogZ0OfkmX/DEppehus7L3TS2Q4lpB+hYyxhkQiYPJ6Mf5/dPg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@ -428,9 +428,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
||||||
"version": "4.37.0",
|
"version": "4.34.9",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.37.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.9.tgz",
|
||||||
"integrity": "sha512-jUb/kmn/Gd8epbHKEqkRAxq5c2EwRt0DqhSGWjPFxLeFvldFdHQs/n8lQ9x85oAeVb6bHcS8irhTJX2FCOd8Ag==",
|
"integrity": "sha512-3qyfWljSFHi9zH0KgtEPG4cBXHDFhwD8kwg6xLfHQ0IWuH9crp005GfoUUh/6w9/FWGBwEHg3lxK1iHRN1MFlA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@ -440,9 +440,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||||
"version": "4.37.0",
|
"version": "4.34.9",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.37.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.9.tgz",
|
||||||
"integrity": "sha512-oNrJxcQT9IcbcmKlkF+Yz2tmOxZgG9D9GRq+1OE6XCQwCVwxixYAa38Z8qqPzQvzt1FCfmrHX03E0pWoXm1DqA==",
|
"integrity": "sha512-6TZjPHjKZUQKmVKMUowF3ewHxctrRR09eYyvT5eFv8w/fXarEra83A2mHTVJLA5xU91aCNOUnM+DWFMSbQ0Nxw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -452,9 +452,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||||
"version": "4.37.0",
|
"version": "4.34.9",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.37.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.9.tgz",
|
||||||
"integrity": "sha512-pfxLBMls+28Ey2enpX3JvjEjaJMBX5XlPCZNGxj4kdJyHduPBXtxYeb8alo0a7bqOoWZW2uKynhHxF/MWoHaGQ==",
|
"integrity": "sha512-LD2fytxZJZ6xzOKnMbIpgzFOuIKlxVOpiMAXawsAZ2mHBPEYOnLRK5TTEsID6z4eM23DuO88X0Tq1mErHMVq0A==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -464,9 +464,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-loongarch64-gnu": {
|
"node_modules/@rollup/rollup-linux-loongarch64-gnu": {
|
||||||
"version": "4.37.0",
|
"version": "4.34.9",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.37.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.9.tgz",
|
||||||
"integrity": "sha512-yCE0NnutTC/7IGUq/PUHmoeZbIwq3KRh02e9SfFh7Vmc1Z7atuJRYWhRME5fKgT8aS20mwi1RyChA23qSyRGpA==",
|
"integrity": "sha512-dRAgTfDsn0TE0HI6cmo13hemKpVHOEyeciGtvlBTkpx/F65kTvShtY/EVyZEIfxFkV5JJTuQ9tP5HGBS0hfxIg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"loong64"
|
"loong64"
|
||||||
],
|
],
|
||||||
@ -476,9 +476,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
|
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
|
||||||
"version": "4.37.0",
|
"version": "4.34.9",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.37.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.9.tgz",
|
||||||
"integrity": "sha512-NxcICptHk06E2Lh3a4Pu+2PEdZ6ahNHuK7o6Np9zcWkrBMuv21j10SQDJW3C9Yf/A/P7cutWoC/DptNLVsZ0VQ==",
|
"integrity": "sha512-PHcNOAEhkoMSQtMf+rJofwisZqaU8iQ8EaSps58f5HYll9EAY5BSErCZ8qBDMVbq88h4UxaNPlbrKqfWP8RfJA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
@ -488,21 +488,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
||||||
"version": "4.37.0",
|
"version": "4.34.9",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.37.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.9.tgz",
|
||||||
"integrity": "sha512-PpWwHMPCVpFZLTfLq7EWJWvrmEuLdGn1GMYcm5MV7PaRgwCEYJAwiN94uBuZev0/J/hFIIJCsYw4nLmXA9J7Pw==",
|
"integrity": "sha512-Z2i0Uy5G96KBYKjeQFKbbsB54xFOL5/y1P5wNBsbXB8yE+At3oh0DVMjQVzCJRJSfReiB2tX8T6HUFZ2k8iaKg==",
|
||||||
"cpu": [
|
|
||||||
"riscv64"
|
|
||||||
],
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@rollup/rollup-linux-riscv64-musl": {
|
|
||||||
"version": "4.37.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.37.0.tgz",
|
|
||||||
"integrity": "sha512-DTNwl6a3CfhGTAOYZ4KtYbdS8b+275LSLqJVJIrPa5/JuIufWWZ/QFvkxp52gpmguN95eujrM68ZG+zVxa8zHA==",
|
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"riscv64"
|
"riscv64"
|
||||||
],
|
],
|
||||||
@ -512,9 +500,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
||||||
"version": "4.37.0",
|
"version": "4.34.9",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.37.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.9.tgz",
|
||||||
"integrity": "sha512-hZDDU5fgWvDdHFuExN1gBOhCuzo/8TMpidfOR+1cPZJflcEzXdCy1LjnklQdW8/Et9sryOPJAKAQRw8Jq7Tg+A==",
|
"integrity": "sha512-U+5SwTMoeYXoDzJX5dhDTxRltSrIax8KWwfaaYcynuJw8mT33W7oOgz0a+AaXtGuvhzTr2tVKh5UO8GVANTxyQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"s390x"
|
"s390x"
|
||||||
],
|
],
|
||||||
@ -524,9 +512,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||||
"version": "4.37.0",
|
"version": "4.34.9",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.37.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.9.tgz",
|
||||||
"integrity": "sha512-pKivGpgJM5g8dwj0ywBwe/HeVAUSuVVJhUTa/URXjxvoyTT/AxsLTAbkHkDHG7qQxLoW2s3apEIl26uUe08LVQ==",
|
"integrity": "sha512-FwBHNSOjUTQLP4MG7y6rR6qbGw4MFeQnIBrMe161QGaQoBQLqSUEKlHIiVgF3g/mb3lxlxzJOpIBhaP+C+KP2A==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -536,9 +524,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||||
"version": "4.37.0",
|
"version": "4.34.9",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.37.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.9.tgz",
|
||||||
"integrity": "sha512-E2lPrLKE8sQbY/2bEkVTGDEk4/49UYRVWgj90MY8yPjpnGBQ+Xi1Qnr7b7UIWw1NOggdFQFOLZ8+5CzCiz143w==",
|
"integrity": "sha512-cYRpV4650z2I3/s6+5/LONkjIz8MBeqrk+vPXV10ORBnshpn8S32bPqQ2Utv39jCiDcO2eJTuSlPXpnvmaIgRA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -548,9 +536,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||||
"version": "4.37.0",
|
"version": "4.34.9",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.37.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.9.tgz",
|
||||||
"integrity": "sha512-Jm7biMazjNzTU4PrQtr7VS8ibeys9Pn29/1bm4ph7CP2kf21950LgN+BaE2mJ1QujnvOc6p54eWWiVvn05SOBg==",
|
"integrity": "sha512-z4mQK9dAN6byRA/vsSgQiPeuO63wdiDxZ9yg9iyX2QTzKuQM7T4xlBoeUP/J8uiFkqxkcWndWi+W7bXdPbt27Q==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -560,9 +548,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||||
"version": "4.37.0",
|
"version": "4.34.9",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.37.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.9.tgz",
|
||||||
"integrity": "sha512-e3/1SFm1OjefWICB2Ucstg2dxYDkDTZGDYgwufcbsxTHyqQps1UQf33dFEChBNmeSsTOyrjw2JJq0zbG5GF6RA==",
|
"integrity": "sha512-KB48mPtaoHy1AwDNkAJfHXvHp24H0ryZog28spEs0V48l3H1fr4i37tiyHsgKZJnCmvxsbATdZGBpbmxTE3a9w==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
@ -572,9 +560,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||||
"version": "4.37.0",
|
"version": "4.34.9",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.37.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.9.tgz",
|
||||||
"integrity": "sha512-LWbXUBwn/bcLx2sSsqy7pK5o+Nr+VCoRoAohfJ5C/aBio9nfJmGQqHAhU6pwxV/RmyTk5AqdySma7uwWGlmeuA==",
|
"integrity": "sha512-AyleYRPU7+rgkMWbEh71fQlrzRfeP6SyMnRf9XX4fCdDPAJumdSBqYEcWPMzVQ4ScAl7E4oFfK0GUVn77xSwbw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -584,9 +572,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@types/estree": {
|
"node_modules/@types/estree": {
|
||||||
"version": "1.0.7",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
|
||||||
"integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ=="
|
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="
|
||||||
},
|
},
|
||||||
"node_modules/@types/resolve": {
|
"node_modules/@types/resolve": {
|
||||||
"version": "1.20.2",
|
"version": "1.20.2",
|
||||||
@ -745,9 +733,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/rollup": {
|
"node_modules/rollup": {
|
||||||
"version": "4.37.0",
|
"version": "4.34.9",
|
||||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.37.0.tgz",
|
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.9.tgz",
|
||||||
"integrity": "sha512-iAtQy/L4QFU+rTJ1YUjXqJOJzuwEghqWzCEYD2FEghT7Gsy1VdABntrO4CLopA5IkflTyqNiLNwPcOJ3S7UKLg==",
|
"integrity": "sha512-nF5XYqWWp9hx/LrpC8sZvvvmq0TeTjQgaZHYmAgwysT9nh8sWnZhBnM8ZyVbbJFIQBLwHDNoMqsBZBbUo4U8sQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/estree": "1.0.6"
|
"@types/estree": "1.0.6"
|
||||||
},
|
},
|
||||||
@ -759,34 +747,28 @@
|
|||||||
"npm": ">=8.0.0"
|
"npm": ">=8.0.0"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@rollup/rollup-android-arm-eabi": "4.37.0",
|
"@rollup/rollup-android-arm-eabi": "4.34.9",
|
||||||
"@rollup/rollup-android-arm64": "4.37.0",
|
"@rollup/rollup-android-arm64": "4.34.9",
|
||||||
"@rollup/rollup-darwin-arm64": "4.37.0",
|
"@rollup/rollup-darwin-arm64": "4.34.9",
|
||||||
"@rollup/rollup-darwin-x64": "4.37.0",
|
"@rollup/rollup-darwin-x64": "4.34.9",
|
||||||
"@rollup/rollup-freebsd-arm64": "4.37.0",
|
"@rollup/rollup-freebsd-arm64": "4.34.9",
|
||||||
"@rollup/rollup-freebsd-x64": "4.37.0",
|
"@rollup/rollup-freebsd-x64": "4.34.9",
|
||||||
"@rollup/rollup-linux-arm-gnueabihf": "4.37.0",
|
"@rollup/rollup-linux-arm-gnueabihf": "4.34.9",
|
||||||
"@rollup/rollup-linux-arm-musleabihf": "4.37.0",
|
"@rollup/rollup-linux-arm-musleabihf": "4.34.9",
|
||||||
"@rollup/rollup-linux-arm64-gnu": "4.37.0",
|
"@rollup/rollup-linux-arm64-gnu": "4.34.9",
|
||||||
"@rollup/rollup-linux-arm64-musl": "4.37.0",
|
"@rollup/rollup-linux-arm64-musl": "4.34.9",
|
||||||
"@rollup/rollup-linux-loongarch64-gnu": "4.37.0",
|
"@rollup/rollup-linux-loongarch64-gnu": "4.34.9",
|
||||||
"@rollup/rollup-linux-powerpc64le-gnu": "4.37.0",
|
"@rollup/rollup-linux-powerpc64le-gnu": "4.34.9",
|
||||||
"@rollup/rollup-linux-riscv64-gnu": "4.37.0",
|
"@rollup/rollup-linux-riscv64-gnu": "4.34.9",
|
||||||
"@rollup/rollup-linux-riscv64-musl": "4.37.0",
|
"@rollup/rollup-linux-s390x-gnu": "4.34.9",
|
||||||
"@rollup/rollup-linux-s390x-gnu": "4.37.0",
|
"@rollup/rollup-linux-x64-gnu": "4.34.9",
|
||||||
"@rollup/rollup-linux-x64-gnu": "4.37.0",
|
"@rollup/rollup-linux-x64-musl": "4.34.9",
|
||||||
"@rollup/rollup-linux-x64-musl": "4.37.0",
|
"@rollup/rollup-win32-arm64-msvc": "4.34.9",
|
||||||
"@rollup/rollup-win32-arm64-msvc": "4.37.0",
|
"@rollup/rollup-win32-ia32-msvc": "4.34.9",
|
||||||
"@rollup/rollup-win32-ia32-msvc": "4.37.0",
|
"@rollup/rollup-win32-x64-msvc": "4.34.9",
|
||||||
"@rollup/rollup-win32-x64-msvc": "4.37.0",
|
|
||||||
"fsevents": "~2.3.2"
|
"fsevents": "~2.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/rollup/node_modules/@types/estree": {
|
|
||||||
"version": "1.0.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
|
|
||||||
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="
|
|
||||||
},
|
|
||||||
"node_modules/safe-buffer": {
|
"node_modules/safe-buffer": {
|
||||||
"version": "5.2.1",
|
"version": "5.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||||
|
@ -1 +1 @@
|
|||||||
A Secure Scuttlebutt decentralized social network client
|
A tool for making and sharing
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<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="35"
|
android:versionCode="34"
|
||||||
android:versionName="0.0.30-wip">
|
android:versionName="0.0.29">
|
||||||
<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
|
||||||
|
@ -347,6 +347,7 @@ public class TildeFriendsActivity extends Activity {
|
|||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (java.io.FileNotFoundException e) {
|
} catch (java.io.FileNotFoundException e) {
|
||||||
|
Log.w("tildefriends", "Port file does not yet exist.");
|
||||||
} catch (java.io.IOException e) {
|
} catch (java.io.IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
32
src/http.c
32
src/http.c
@ -785,25 +785,8 @@ void tf_http_add_handler(tf_http_t* http, const char* pattern, tf_http_callback_
|
|||||||
static void _http_free_listener_on_close(uv_handle_t* handle)
|
static void _http_free_listener_on_close(uv_handle_t* handle)
|
||||||
{
|
{
|
||||||
tf_http_listener_t* listener = handle->data;
|
tf_http_listener_t* listener = handle->data;
|
||||||
tf_http_t* http = listener->http;
|
|
||||||
for (int i = 0; i < http->listeners_count; i++)
|
|
||||||
{
|
|
||||||
if (http->listeners[i] == listener)
|
|
||||||
{
|
|
||||||
http->listeners[i] = http->listeners[http->listeners_count - 1];
|
|
||||||
http->listeners_count--;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
handle->data = NULL;
|
handle->data = NULL;
|
||||||
tf_free(listener);
|
tf_free(listener);
|
||||||
|
|
||||||
if (!http->listeners_count)
|
|
||||||
{
|
|
||||||
tf_free(http->listeners);
|
|
||||||
http->listeners = NULL;
|
|
||||||
tf_http_destroy(http);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void tf_http_destroy(tf_http_t* http)
|
void tf_http_destroy(tf_http_t* http)
|
||||||
@ -829,10 +812,6 @@ void tf_http_destroy(tf_http_t* http)
|
|||||||
listener->cleanup(listener->user_data);
|
listener->cleanup(listener->user_data);
|
||||||
listener->cleanup = NULL;
|
listener->cleanup = NULL;
|
||||||
}
|
}
|
||||||
if (listener->tcp.data && !uv_is_closing((uv_handle_t*)&listener->tcp))
|
|
||||||
{
|
|
||||||
uv_close((uv_handle_t*)&listener->tcp, _http_free_listener_on_close);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < http->handlers_count; i++)
|
for (int i = 0; i < http->handlers_count; i++)
|
||||||
@ -850,11 +829,20 @@ void tf_http_destroy(tf_http_t* http)
|
|||||||
http->user_data = NULL;
|
http->user_data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (http->connections_count == 0 && http->listeners_count == 0)
|
if (http->connections_count == 0)
|
||||||
{
|
{
|
||||||
tf_free(http->connections);
|
tf_free(http->connections);
|
||||||
http->connections = NULL;
|
http->connections = NULL;
|
||||||
|
|
||||||
|
for (int i = 0; i < http->listeners_count; i++)
|
||||||
|
{
|
||||||
|
tf_http_listener_t* listener = http->listeners[i];
|
||||||
|
uv_close((uv_handle_t*)&listener->tcp, _http_free_listener_on_close);
|
||||||
|
}
|
||||||
|
tf_free(http->listeners);
|
||||||
|
http->listeners = NULL;
|
||||||
|
http->listeners_count = 0;
|
||||||
|
|
||||||
for (int i = 0; i < http->handlers_count; i++)
|
for (int i = 0; i < http->handlers_count; i++)
|
||||||
{
|
{
|
||||||
if (http->handlers[i].pattern)
|
if (http->handlers[i].pattern)
|
||||||
|
@ -13,13 +13,13 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>0.0.30</string>
|
<string>0.0.29</string>
|
||||||
<key>CFBundleSupportedPlatforms</key>
|
<key>CFBundleSupportedPlatforms</key>
|
||||||
<array>
|
<array>
|
||||||
<string>iPhoneOS</string>
|
<string>iPhoneOS</string>
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>12</string>
|
<string>11</string>
|
||||||
<key>DTPlatformName</key>
|
<key>DTPlatformName</key>
|
||||||
<string>iphoneos</string>
|
<string>iphoneos</string>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
|
16
src/ssb.db.c
16
src/ssb.db.c
@ -176,19 +176,13 @@ void tf_ssb_db_init(tf_ssb_t* ssb)
|
|||||||
_tf_ssb_db_exec(db, "ALTER TABLE messages RENAME COLUMN sequence_before_author TO flags");
|
_tf_ssb_db_exec(db, "ALTER TABLE messages RENAME COLUMN sequence_before_author TO flags");
|
||||||
}
|
}
|
||||||
|
|
||||||
_tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_id_author_index ON messages (id, author)");
|
_tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_author_id_index ON messages (author, id)");
|
||||||
_tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_author_sequence_index ON messages (author, sequence)");
|
_tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_author_sequence_index ON messages (author, sequence)");
|
||||||
_tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_author_timestamp_index ON messages (author, timestamp)");
|
_tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_author_timestamp_index ON messages (author, timestamp)");
|
||||||
_tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_timestamp_index ON messages (timestamp)");
|
_tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_timestamp_index ON messages (timestamp)");
|
||||||
_tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_type_timestamp_index ON messages (content ->> 'type', timestamp)");
|
_tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_type_timestamp_index ON messages (content ->> 'type', timestamp)");
|
||||||
_tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_size_by_author_index ON messages (author, length(content))");
|
_tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_size_by_author_index ON messages (author, length(content))");
|
||||||
_tf_ssb_db_exec(
|
_tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_type_author_channel_index ON messages (content ->> 'type', author, content ->> 'channel');");
|
||||||
db, "CREATE INDEX IF NOT EXISTS messages_type_author_channel_root_rowid_index ON messages (author, content ->> 'type', content ->> 'channel', content ->> 'root')");
|
|
||||||
_tf_ssb_db_exec(db, "DROP INDEX IF EXISTS messages_type_author_channel_index");
|
|
||||||
_tf_ssb_db_exec(db, "DROP INDEX IF EXISTS messages_author_id_index");
|
|
||||||
_tf_ssb_db_exec(db, "DROP INDEX IF EXISTS messages_by_author_index");
|
|
||||||
_tf_ssb_db_exec(db, "DROP INDEX IF EXISTS messages_timestamp_author_index");
|
|
||||||
_tf_ssb_db_exec(db, "DROP INDEX IF EXISTS messages_id_index");
|
|
||||||
_tf_ssb_db_exec(db,
|
_tf_ssb_db_exec(db,
|
||||||
"CREATE TABLE IF NOT EXISTS blobs ("
|
"CREATE TABLE IF NOT EXISTS blobs ("
|
||||||
" id TEXT PRIMARY KEY,"
|
" id TEXT PRIMARY KEY,"
|
||||||
@ -292,10 +286,8 @@ void tf_ssb_db_init(tf_ssb_t* ssb)
|
|||||||
_tf_ssb_db_exec(db, "DROP TRIGGER IF EXISTS messages_ad_refs");
|
_tf_ssb_db_exec(db, "DROP TRIGGER IF EXISTS messages_ad_refs");
|
||||||
_tf_ssb_db_exec(db, "CREATE TRIGGER IF NOT EXISTS messages_ad_refs AFTER DELETE ON messages BEGIN DELETE FROM messages_refs WHERE messages_refs.message = old.id; END");
|
_tf_ssb_db_exec(db, "CREATE TRIGGER IF NOT EXISTS messages_ad_refs AFTER DELETE ON messages BEGIN DELETE FROM messages_refs WHERE messages_refs.message = old.id; END");
|
||||||
|
|
||||||
_tf_ssb_db_exec(db, "DROP INDEX IF EXISTS messages_refs_message_idx");
|
_tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_refs_message_idx ON messages_refs (message)");
|
||||||
_tf_ssb_db_exec(db, "DROP INDEX IF EXISTS messages_refs_ref_idx");
|
_tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_refs_ref_idx ON messages_refs (ref)");
|
||||||
_tf_ssb_db_exec(db, "CREATE UNIQUE INDEX IF NOT EXISTS messages_refs_message_ref_idx ON messages_refs (message, ref)");
|
|
||||||
_tf_ssb_db_exec(db, "CREATE UNIQUE INDEX IF NOT EXISTS messages_refs_ref_message_idx ON messages_refs (ref, message)");
|
|
||||||
|
|
||||||
if (!_tf_ssb_db_has_rows(db, "PRAGMA table_list('blobs_refs')"))
|
if (!_tf_ssb_db_has_rows(db, "PRAGMA table_list('blobs_refs')"))
|
||||||
{
|
{
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
#define VERSION_NUMBER "0.0.30-wip"
|
#define VERSION_NUMBER "0.0.29"
|
||||||
#define VERSION_NAME "This program kills fascists."
|
#define VERSION_NAME "This program kills fascists."
|
||||||
|
@ -17,7 +17,6 @@ k_feeds = {
|
|||||||
'habitat': 'https://tildegit.org/jeremylist/habitat.rss',
|
'habitat': 'https://tildegit.org/jeremylist/habitat.rss',
|
||||||
'manyverse': 'https://gitlab.com/staltz/manyverse/-/commits/master?format=atom',
|
'manyverse': 'https://gitlab.com/staltz/manyverse/-/commits/master?format=atom',
|
||||||
'ahau': 'https://gitlab.com/ahau/ahau/-/commits/master.atom',
|
'ahau': 'https://gitlab.com/ahau/ahau/-/commits/master.atom',
|
||||||
'patchfox': 'https://github.com/soapdog/patchfox/commits.atom',
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def fix_title(entry):
|
def fix_title(entry):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user