Compare commits

...

70 commits

Author SHA1 Message Date
dakkar e00f1a5e56 merge: handle non-ASCII emoji names (!464)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/464
2024-04-12 03:16:06 +00:00
dakkar e0afeff248 merge: hide images/videos in og cards, when under a CW - fixes #487 (!488)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/488

Closes #487

Approved-by: Marie <marie@kaifa.ch>
Approved-by: Amelia Yukii <amelia.yukii@shourai.de>
2024-04-11 20:40:38 +00:00
Marie cfc8081cec merge: bump tmp@0.2.3 - fixes #464 (!475)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/475

Closes #464

Approved-by: Marie <marie@kaifa.ch>
Approved-by: Luna <her@mint.lgbt>
Approved-by: Amelia Yukii <amelia.yukii@shourai.de>
2024-04-11 18:00:40 +00:00
Marie 011ccd3a9a merge: bump devel version (!486)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/486

Approved-by: Marie <marie@kaifa.ch>
Approved-by: Amelia Yukii <amelia.yukii@shourai.de>
2024-04-11 17:21:32 +00:00
Amelia Yukii 28065fc1d1 merge: handle ranged requests for proxied files - fixes #494 (!490)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/490

Closes #494

Approved-by: Amelia Yukii <amelia.yukii@shourai.de>
Approved-by: Marie <marie@kaifa.ch>
2024-04-11 10:07:25 +00:00
dakkar 960f4fcff7 detect size of remote files - fixes #494
without this, remote files are assumed to have size 0 (even if we just
downloaded them!) and the range-related code won't run
2024-04-09 16:21:30 +01:00
dakkar 92eec2178f return 206 for every ranged response - fixes #494 2024-04-09 15:42:29 +01:00
dakkar 56dca6dbf5 hide images/videos in og cards, when under a CW - fixes #487 2024-04-07 16:58:13 +01:00
Marie bb7b4a8ea4 merge: fix: send null for empty edited_at in mastodon api (!487)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/487

Approved-by: dakkar <dakkar@thenautilus.net>
Approved-by: Marie <marie@kaifa.ch>
2024-04-07 15:36:59 +00:00
dakkar 0690b9a429 merge: fix: load libopenmpt on demand (!469)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/469

Approved-by: dakkar <dakkar@thenautilus.net>
Approved-by: Marie <marie@kaifa.ch>
2024-04-07 14:56:16 +00:00
Sugar🍬🍭🏳️‍⚧ e779c1e667 fix: send null for empty edited_at in mastodon api 2024-04-04 10:43:28 +02:00
Marie 8c955fcce5 merge: use correct note design in favorites page - fixes #483 (!481)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/481

Closes #483

Approved-by: Amelia Yukii <amelia.yukii@shourai.de>
Approved-by: Marie <marie@kaifa.ch>
2024-04-03 09:28:01 +00:00
dakkar 2a634e0309 bump devel version 2024-03-30 12:48:03 +00:00
dakkar e6970a0e7c Merge branch 'stable' into bump-devel-version 2024-03-30 12:44:31 +00:00
Amelia Yukii 571272a564 merge: release 2024.3.2 (!485)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/485

Approved-by: Amelia Yukii <amelia.yukii@shourai.de>
2024-03-30 11:19:08 +00:00
dakkar 30bb0f60a2 version bump 2024-03-30 11:09:00 +00:00
dakkar 328546c4cd Merge branch 'develop' into release/2024-03-30 2024-03-30 11:08:26 +00:00
Amelia Yukii 126248e58d merge: some validation fixes (!484)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/484

Closes #469

Approved-by: Amelia Yukii <amelia.yukii@shourai.de>
2024-03-30 11:05:58 +00:00
dakkar 074de82bf7 some validation fixes 2024-03-30 11:05:58 +00:00
dakkar bd7c4f66f3 use correct note design in favorites page - fixes #483 2024-03-27 16:03:35 +00:00
dakkar f4e89f2e6b bump tmp@0.2.3 - fixes #464
see also https://github.com/raszi/node-tmp/issues/295
2024-03-19 17:13:43 +00:00
Alina Sireneva ecfaf7ff7a chore: added license and patch info 2024-03-14 21:39:34 +03:00
dakkar 58bc8f2c10 merge: always align code to the left - fixes #436 (!453)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/453

Closes #436

Approved-by: Essem <smswessem@gmail.com>
Approved-by: Leah <kevinlukej@gmail.com>
2024-03-14 14:48:30 +00:00
dakkar 94aed953b5 merge: make cookie a bit more secure - fixes #445 (!468)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/468

Closes #445

Approved-by: Luna <her@mint.lgbt>
Approved-by: Amelia Yukii <amelia.yukii@shourai.de>
2024-03-14 14:47:38 +00:00
dakkar aa7035a35a merge: longer statement_timeout for migrations - fixes 450 (!466)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/466

Approved-by: Luna <her@mint.lgbt>
Approved-by: Amelia Yukii <amelia.yukii@shourai.de>
2024-03-14 14:46:42 +00:00
dakkar 45eab01fc4 merge: hide CW-ed featured notes on welcome page - fixes #458 (!467)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/467

Closes #458

Approved-by: Amelia Yukii <amelia.yukii@shourai.de>
Approved-by: Leah <kevinlukej@gmail.com>
Approved-by: Marie <marie@kaifa.ch>
2024-03-14 14:45:53 +00:00
Marie 71bcd76cc5 merge: Update IMPORTANT_NOTES.md (!470)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/470

Approved-by: Amelia Yukii <amelia.yukii@shourai.de>
Approved-by: Marie <marie@kaifa.ch>
Approved-by: dakkar <dakkar@thenautilus.net>
2024-03-14 11:53:15 +00:00
Alina Sireneva a69315a24b fix: added wasm in vite config 2024-03-14 14:41:24 +03:00
Luna d003c3ec1f merge: Fixed broken line numbers (!471)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/471

Approved-by: Amelia Yukii <amelia.yukii@shourai.de>
Approved-by: Luna <her@mint.lgbt>
2024-03-14 01:36:46 +00:00
KevinWh0 b918f38ec2 fixed 2024-03-13 23:52:21 +01:00
Dalek cdb82c0ade Update IMPORTANT_NOTES.md 2024-03-13 00:17:57 +00:00
Alina Sireneva d991eccd3f fix: Promise.resolve 2024-03-11 16:42:10 +03:00
Alina Sireneva 0085305579 fix: load libopenmpt on demand 2024-03-11 15:32:59 +03:00
dakkar 6826e43ad7 make cookie a bit more secure - fixes #445
We can't make the cookie `HttpOnly` because we're setting it from
Javascript, but I'm not sure it's worth the trouble to redesign that:
`JSON.parse(localStorage.account).token` gives you the token anyway,
hiding the cookie from JS won't offer much protection.

At least we can mark is `Secure` (meaning, only send it over HTTPS)
and _delete it on logout_ (it wasn't!)
2024-03-10 10:26:04 +00:00
dakkar ff189b1952 hide CW-ed featured notes on welcome page - fixes #458
not the most elegant solution, but simple and robust
2024-03-10 10:13:35 +00:00
dakkar 43544a6479 longer statement_timeout for migrations - fixes 450 2024-03-09 15:38:36 +00:00
dakkar 03464cc379 always align code to the left - fixes #436
"featured notes" on the welcome page's right-hand column are shown
with the text right-aligned; code should not be affected by that. This
makes sure it isn't
2024-03-03 12:06:22 +00:00
dakkar 2cad97c1ab merge: release 2024.3.1 (!449)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/449

Approved-by: Amelia Yukii <amelia.yukii@shourai.de>
Approved-by: Marie <marie@kaifa.ch>
2024-03-02 17:43:24 +00:00
dakkar 6ecfe7c7c3 remove duplicate method 2024-03-02 17:34:31 +00:00
dakkar 23f476dbf3 Merge branch 'develop' into release/2024.3.1 2024-03-02 17:28:34 +00:00
Amelia Yukii 7a1251423f merge: Add missing IMPORTANT_NOTES.md from Sharkey/OldJoinSharkey (!443)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/443

Approved-by: dakkar <dakkar@thenautilus.net>
Approved-by: Amelia Yukii <amelia.yukii@shourai.de>
2024-02-24 18:20:48 +00:00
Marie 7f5492a395 Add missing IMPORTANT_NOTES.md from Sharkey/OldJoinSharkey 2024-02-24 18:20:48 +00:00
Amelia Yukii 11d9fd9199 merge: import upstream ssrf fix on our stable (!425)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/425

Approved-by: Leah <kevinlukej@gmail.com>
Approved-by: Amelia Yukii <amelia.yukii@shourai.de>
2024-02-17 13:06:47 +00:00
syuilo 6132bc3b3e fix of 9a70ce8f5e
Co-Authored-By: RyotaK <49341894+Ry0taK@users.noreply.github.com>
2024-02-17 12:54:45 +00:00
dakkar fef7a7b99a bump version 2024-02-17 12:38:01 +00:00
tamaina 1948ca9aa8 Merge pull request from GHSA-qqrm-9grj-6v32 2024-02-17 12:36:44 +00:00
Amelia Yukii 848e1f9a56 version is better
(cherry picked from commit fb455e4fd9)
2024-02-01 16:11:48 +00:00
Amelia Yukii 9c4353ee79 Update .gitlab-ci.yml
(cherry picked from commit 8c5818acf0)
2024-02-01 16:10:47 +00:00
Amelia Yukii a6e257f502 Merge branch 'feture/code-injection-fix' into 'develop'
CVE: Fixed code injection from twitter import

See merge request TransFem-org/Sharkey!390

(cherry picked from commit 127f8556d4)

2a8e93e4 Fixed code injection from twitter import
2024-02-01 15:07:35 +00:00
Amelia Yukii 310e1a1262 Merge branch 'Amelia-stable-patch-29368' into 'stable'
Update docker-compose_example.yml

See merge request TransFem-org/Sharkey!389
2024-02-01 14:44:14 +00:00
Amelia Yukii 15f3c046d1 Update docker-compose_example.yml 2024-02-01 14:42:19 +00:00
Amelia Yukii 01d695428a Revert "build stable with stable tag"
This reverts commit acf3e3460f
2024-02-01 14:15:10 +00:00
Amelia Yukii acf3e3460f build stable with stable tag 2024-02-01 14:00:56 +00:00
Amelia Yukii 4c8116859c Revert "Merge branch 'cherry-pick-3b2d47b1' into 'stable'"
This reverts merge request !386
2024-02-01 13:55:44 +00:00
Amelia Yukii 0e13397db7 Merge branch 'cherry-pick-3b2d47b1' into 'stable'
build stable with stable tag

See merge request TransFem-org/Sharkey!386
2024-02-01 13:41:34 +00:00
Amelia Yukii ad8818508f Update file .gitlab-ci.yml
(cherry picked from commit 3b2d47b1e3)
2024-02-01 13:38:19 +00:00
Amelia Yukii d444ee662f Merge branch 'cherry-pick-522ab39d' into 'stable'
Merge branch 'gitlab-ci' into 'develop'

See merge request TransFem-org/Sharkey!383
2024-02-01 10:23:23 +00:00
Amelia Yukii 4c354fff2d Merge branch 'gitlab-ci' into 'develop' 2024-02-01 10:23:23 +00:00
Marie b81448edf6 merge: release 2023.12.0 2023-12-31 23:19:41 +01:00
Marie 134d2895f0 fix: merge conflict 2023-12-31 23:11:15 +01:00
Marie 7ba8fde9b9 chore: change version 2023-12-31 22:49:43 +01:00
Marie 1022280465
release: 2023.11.2 2023-12-01 00:01:19 +01:00
Marie 021d3924e6
chore: change version 2023-11-30 23:57:04 +01:00
Mar0xy b6d50d781f
Merge branch 'stable' of https://github.com/transfem-org/Sharkey into stable 2023-11-26 18:47:44 +01:00
Mar0xy 1d411bb885
chore: fix locales 2023-11-26 18:47:20 +01:00
Marie f7afd1ae4a
release: 2023.11.1 2023-11-26 17:28:42 +01:00
Marie 1ef1f2a03c
Merge branch 'stable' into release/2023.11.1 2023-11-26 17:26:30 +01:00
Marie 829ce4f86a
merge: 2023.11.0 2023-11-07 20:16:20 +01:00
Mar0xy 6d5d863150
merge: last minute changes 2023-11-07 20:07:53 +01:00
Marie fc7d4bc420
chore: set release version 2023-11-07 19:39:18 +01:00
42 changed files with 228 additions and 47 deletions

View file

@ -55,6 +55,8 @@ getImageTag:
only:
- stable
- develop
- tags
buildDocker:
stage: deploy
needs:
@ -78,6 +80,8 @@ buildDocker:
only:
- stable
- develop
- tags
mergeManifests:
stage: deploy
needs:
@ -103,3 +107,4 @@ mergeManifests:
only:
- stable
- develop
- tags

View file

@ -6,8 +6,11 @@ When using a service with Sharkey, there are several important points to keep in
2. Even for posts made in private, there is no guarantee that the recipient's server will treat them as private in the same way. Please exercise caution when posting personal or confidential information. (Again, this applies to the internet in general.)
3. Account deletion can be a resource-intensive process and may take a long time. In cases with a lot of uploaded data, it may even be impossible to delete an account.
3. The "Drive" feature is NOT secure cloud storage. This feature exists for easier managing of your uploaded files.
Any data uploaded, whether shared via post or not, will be publicly accessible. Please use 3rd party cloud storage providers if you need to upload data with sensitive information of any kind.
4. Please disable ad blockers. Some servers may rely on advertising revenue to cover operating costs. Additionally, ad blockers can mistakenly block content and features unrelated to ads, potentially causing issues with the client's functionality and preventing normal use of Sharkey. Therefore, we recommend turning off ad blockers and similar features when using Sharkey.
4. Account deletion can be a resource-intensive process and may take a long time. In cases with a lot of uploaded data, it may even be impossible to delete an account.
5. Please disable ad blockers. Some servers may rely on advertising revenue to cover operating costs. Additionally, ad blockers can mistakenly block content and features unrelated to ads, potentially causing issues with the client's functionality and preventing normal use of Sharkey. Therefore, we recommend turning off ad blockers and similar features when using Sharkey.
Please understand these points and enjoy using the service.

View file

@ -1,6 +1,6 @@
{
"name": "sharkey",
"version": "2024.3.1",
"version": "2024.3.2-devel",
"codename": "shonk",
"repository": {
"type": "git",

View file

@ -11,7 +11,11 @@ export default new DataSource({
username: config.db.user,
password: config.db.pass,
database: config.db.db,
extra: config.db.extra,
extra: {
...config.db.extra,
// migrations may be very slow, give them longer to run (that 10*1000 comes from postgres.ts)
statement_timeout: (config.db.extra?.statement_timeout ?? 1000 * 10) * 10,
},
entities: entities,
migrations: ['migration/*.js'],
});

View file

@ -172,7 +172,7 @@
"stringz": "2.1.0",
"systeminformation": "5.22.0",
"tinycolor2": "1.6.0",
"tmp": "0.2.2",
"tmp": "0.2.3",
"tsc-alias": "1.8.8",
"tsconfig-paths": "4.2.0",
"typeorm": "0.3.20",

View file

@ -15,6 +15,7 @@ import type { Config } from '@/config.js';
import { StatusError } from '@/misc/status-error.js';
import { bindThis } from '@/decorators.js';
import { validateContentTypeSetAsActivityPub } from '@/core/activitypub/misc/validator.js';
import { assertActivityMatchesUrls } from '@/core/activitypub/misc/check-against-url.js';
import type { IObject } from '@/core/activitypub/type.js';
import type { Response } from 'node-fetch';
import type { URL } from 'node:url';
@ -125,7 +126,12 @@ export class HttpRequestService {
validators: [validateContentTypeSetAsActivityPub],
});
return await res.json() as IObject;
const finalUrl = res.url; // redirects may have been involved
const activity = await res.json() as IObject;
assertActivityMatchesUrls(activity, [url, finalUrl]);
return activity;
}
@bindThis

View file

@ -86,7 +86,7 @@ export class UtilityService {
@bindThis
public extractDbHost(uri: string): string {
const url = new URL(uri);
return this.toPuny(url.hostname);
return this.toPuny(url.host);
}
@bindThis
@ -99,4 +99,11 @@ export class UtilityService {
if (host == null) return null;
return toASCII(host.toLowerCase());
}
@bindThis
public punyHost(url: string): string {
const urlObj = new URL(url);
const host = `${this.toPuny(urlObj.hostname)}${urlObj.port.length > 0 ? ':' + urlObj.port : ''}`;
return host;
}
}

View file

@ -14,7 +14,9 @@ import { HttpRequestService } from '@/core/HttpRequestService.js';
import { LoggerService } from '@/core/LoggerService.js';
import { bindThis } from '@/decorators.js';
import type Logger from '@/logger.js';
import type { IObject } from './type.js';
import { validateContentTypeSetAsActivityPub } from '@/core/activitypub/misc/validator.js';
import { assertActivityMatchesUrls } from '@/core/activitypub/misc/check-against-url.js';
type Request = {
url: string;
@ -201,6 +203,11 @@ export class ApRequestService {
validators: [validateContentTypeSetAsActivityPub],
});
return await res.json();
const finalUrl = res.url; // redirects may have been involved
const activity = await res.json() as IObject;
assertActivityMatchesUrls(activity, [url, finalUrl]);
return activity;
}
}

View file

@ -115,6 +115,14 @@ export class Resolver {
throw new Error('invalid response');
}
// HttpRequestService / ApRequestService have already checked that
// `object.id` or `object.url` matches the URL used to fetch the
// object after redirects; here we double-check that no redirects
// bounced between hosts
if (object.id && (this.utilityService.punyHost(object.id) !== this.utilityService.punyHost(value))) {
throw new Error(`invalid AP object ${value}: id ${object.id} has different host`);
}
return object;
}

View file

@ -0,0 +1,19 @@
/*
* SPDX-FileCopyrightText: dakkar and sharkey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import type { IObject } from '../type.js';
export function assertActivityMatchesUrls(activity: IObject, urls: string[]) {
const idOk = activity.id !== undefined && urls.includes(activity.id);
// technically `activity.url` could be an `ApObject = IObject |
// string | (IObject | string)[]`, but if it's a complicated thing
// and the `activity.id` doesn't match, I think we're fine
// rejecting the activity
const urlOk = typeof(activity.url) === 'string' && urls.includes(activity.url);
if (!idOk && !urlOk) {
throw new Error(`bad Activity: neither id(${activity?.id}) nor url(${activity?.url}) match location(${urls})`);
}
}

View file

@ -127,12 +127,6 @@ export class ApPersonService implements OnModuleInit {
this.logger = this.apLoggerService.logger;
}
private punyHost(url: string): string {
const urlObj = new URL(url);
const host = `${this.utilityService.toPuny(urlObj.hostname)}${urlObj.port.length > 0 ? ':' + urlObj.port : ''}`;
return host;
}
/**
* Validate and convert to actor object
* @param x Fetched object
@ -140,7 +134,7 @@ export class ApPersonService implements OnModuleInit {
*/
@bindThis
private validateActor(x: IObject, uri: string): IActor {
const expectHost = this.punyHost(uri);
const expectHost = this.utilityService.punyHost(uri);
if (!isActor(x)) {
throw new Error(`invalid Actor type '${x.type}'`);
@ -154,6 +148,19 @@ export class ApPersonService implements OnModuleInit {
throw new Error('invalid Actor: wrong inbox');
}
if (this.utilityService.punyHost(x.inbox) !== expectHost) {
throw new Error('invalid Actor: inbox has different host');
}
for (const collection of ['outbox', 'followers', 'following'] as (keyof IActor)[]) {
const collectionUri = (x as IActor)[collection];
if (typeof collectionUri === 'string' && collectionUri.length > 0) {
if (this.utilityService.punyHost(collectionUri) !== expectHost) {
throw new Error(`invalid Actor: ${collection} has different host`);
}
}
}
if (!(typeof x.preferredUsername === 'string' && x.preferredUsername.length > 0 && x.preferredUsername.length <= 128 && /^\w([\w-.]*\w)?$/.test(x.preferredUsername))) {
throw new Error('invalid Actor: wrong username');
}
@ -177,7 +184,7 @@ export class ApPersonService implements OnModuleInit {
x.summary = truncate(x.summary, summaryLength);
}
const idHost = this.punyHost(x.id);
const idHost = this.utilityService.punyHost(x.id);
if (idHost !== expectHost) {
throw new Error('invalid Actor: id has different host');
}
@ -187,7 +194,7 @@ export class ApPersonService implements OnModuleInit {
throw new Error('invalid Actor: publicKey.id is not a string');
}
const publicKeyIdHost = this.punyHost(x.publicKey.id);
const publicKeyIdHost = this.utilityService.punyHost(x.publicKey.id);
if (publicKeyIdHost !== expectHost) {
throw new Error('invalid Actor: publicKey.id has different host');
}
@ -286,7 +293,7 @@ export class ApPersonService implements OnModuleInit {
this.logger.info(`Creating the Person: ${person.id}`);
const host = this.punyHost(object.id);
const host = this.utilityService.punyHost(object.id);
const fields = this.analyzeAttachments(person.attachment ?? []);

View file

@ -192,6 +192,7 @@ export class FileServerService {
reply.header('Content-Range', `bytes ${start}-${end}/${file.file.size}`);
reply.header('Accept-Ranges', 'bytes');
reply.header('Content-Length', chunksize);
reply.code(206);
} else {
image = {
data: fs.createReadStream(file.path),
@ -261,7 +262,6 @@ export class FileServerService {
const parts = range.replace(/bytes=/, '').split('-');
const start = parseInt(parts[0], 10);
let end = parts[1] ? parseInt(parts[1], 10) : file.file.size - 1;
console.log(end);
if (end > file.file.size) {
end = file.file.size - 1;
}
@ -431,6 +431,7 @@ export class FileServerService {
reply.header('Content-Range', `bytes ${start}-${end}/${file.file.size}`);
reply.header('Accept-Ranges', 'bytes');
reply.header('Content-Length', chunksize);
reply.code(206);
} else {
image = {
data: fs.createReadStream(file.path),
@ -527,6 +528,9 @@ export class FileServerService {
if (!file.storedInternal) {
if (!(file.isLink && file.uri)) return '204';
const result = await this.downloadAndDetectTypeFromUrl(file.uri);
if (!file.size) {
file.size = (await fs.promises.stat(result.path)).size;
}
return {
...result,
url: file.uri,

View file

@ -113,8 +113,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
@bindThis
private async fetchAny(uri: string, me: MiLocalUser | null | undefined): Promise<SchemaType<typeof meta['res']> | null> {
// ブロックしてたら中断
const host = this.utilityService.extractDbHost(uri);
const fetchedMeta = await this.metaService.fetch();
if (this.utilityService.isBlockedHost(fetchedMeta.blockedHosts, this.utilityService.extractDbHost(uri))) return null;
if (this.utilityService.isBlockedHost(fetchedMeta.blockedHosts, host)) return null;
let local = await this.mergePack(me, ...await Promise.all([
this.apDbResolverService.getUserFromApId(uri),
@ -122,6 +123,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
]));
if (local != null) return local;
// local object, not found in db? fail
if (this.utilityService.isSelfHost(host)) return null;
// リモートから一旦オブジェクトフェッチ
const resolver = this.apResolverService.createResolver();
const object = await resolver.resolve(uri) as any;

View file

@ -279,7 +279,8 @@ export class MastoConverters {
emoji_reactions: status.emoji_reactions,
bookmarked: false,
quote: isQuote ? await this.convertReblog(status.reblog) : false,
edited_at: note.updatedAt?.toISOString(),
// optional chaining cannot be used, as it evaluates to undefined, not null
edited_at: note.updatedAt ? note.updatedAt.toISOString() : null,
});
}
}

View file

@ -43,7 +43,6 @@ html
link(rel='stylesheet' href='/assets/phosphor-icons/bold/style.css')
link(rel='stylesheet' href='/static-assets/fonts/sharkey-icons/style.css')
link(rel='modulepreload' href=`/vite/${clientEntry.file}`)
script(src='/client-assets/libopenmpt.js')
if !config.clientManifestExists
script(type="module" src="/vite/@vite/client")
@ -73,7 +72,6 @@ html
script.
var VERSION = "#{version}";
var CLIENT_ENTRY = "#{clientEntry.file}";
window.libopenmpt = window.Module;
script(type='application/json' id='misskey_meta' data-generated-at=now)
!= metaJson

View file

@ -5,8 +5,8 @@ block vars
- const title = user.name ? `${user.name} (@${user.username})` : `@${user.username}`;
- const url = `${config.url}/notes/${note.id}`;
- const isRenote = note.renote && note.text == null && note.fileIds.length == 0 && note.poll == null;
- const images = (note.files || []).filter(file => file.type.startsWith('image/') && !file.isSensitive)
- const videos = (note.files || []).filter(file => file.type.startsWith('video/') && !file.isSensitive)
- const images = note.cw ? [] : (note.files || []).filter(file => file.type.startsWith('image/') && !file.isSensitive)
- const videos = note.cw ? [] : (note.files || []).filter(file => file.type.startsWith('video/') && !file.isSensitive)
block title
= `${title} | ${instanceName}`

File diff suppressed because one or more lines are too long

View file

@ -43,6 +43,7 @@ export async function signout() {
waiting();
miLocalStorage.removeItem('account');
await removeAccount($i.id);
document.cookie = `token=; path=/; max-age=0${ location.protocol === 'https:' ? '; Secure' : ''}`;
const accounts = await getAccounts();
//#region Remove service worker registration
@ -200,7 +201,7 @@ export async function login(token: Account['token'], redirect?: string) {
throw reason;
});
miLocalStorage.setItem('account', JSON.stringify(me));
document.cookie = `token=${token}; path=/; max-age=31536000`; // bull dashboardの認証とかで使う
document.cookie = `token=${token}; path=/; max-age=31536000${ location.protocol === 'https:' ? '; Secure' : ''}`; // bull dashboardの認証とかで使う
await addAccount(me.id, token);
if (redirect) {

View file

@ -72,12 +72,16 @@ watch(() => props.lang, (to) => {
</script>
<style module lang="scss">
.codeBlockRoot {
text-align: left;
}
.codeBlockRoot :global(.shiki) > code {
counter-reset: step;
counter-increment: step 0;
}
.codeBlockRoot :global(.shiki) > code > .line::before {
.codeBlockRoot :global(.shiki) > code > span::before {
content: counter(step);
counter-increment: step;
width: 1rem;

View file

@ -55,8 +55,6 @@ import { i18n } from '@/i18n.js';
import { infoImageUrl } from '@/instance.js';
import { defaultStore } from '@/store.js';
console.log(defaultStore.state.noteDesign, defaultStore.state.noteDesign === 'sharkey');
const props = defineProps<{
pagination: Paging;
noGap?: boolean;

View file

@ -16,9 +16,14 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
<template #default="{ items }">
<MkDateSeparatedList v-slot="{ item }" :items="items" :direction="'down'" :noGap="false" :ad="false">
<MkDateSeparatedList v-if="defaultStore.state.noteDesign === 'misskey'"
v-slot="{ item }" :items="items" :direction="'down'" :noGap="false" :ad="false">
<MkNote :key="item.id" :note="item.note" :class="$style.note"/>
</MkDateSeparatedList>
<MkDateSeparatedList v-if="defaultStore.state.noteDesign === 'sharkey'"
v-slot="{ item }" :items="items" :direction="'down'" :noGap="false" :ad="false">
<SkNote :key="item.id" :note="item.note" :class="$style.note"/>
</MkDateSeparatedList>
</template>
</MkPagination>
</MkSpacer>
@ -28,10 +33,12 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup>
import MkPagination from '@/components/MkPagination.vue';
import MkNote from '@/components/MkNote.vue';
import SkNote from '@/components/SkNote.vue';
import MkDateSeparatedList from '@/components/MkDateSeparatedList.vue';
import { i18n } from '@/i18n.js';
import { definePageMetadata } from '@/scripts/page-metadata.js';
import { infoImageUrl } from '@/instance.js';
import { defaultStore } from '@/store.js';
const pagination = {
endpoint: 'i/favorites' as const,

View file

@ -40,7 +40,7 @@ const isScrolling = ref(false);
const scrollEl = shallowRef<HTMLElement>();
misskeyApiGet('notes/featured').then(_notes => {
notes.value = _notes;
notes.value = _notes.filter(n => n.cw == null);
});
onUpdated(() => {

View file

@ -1,9 +1,12 @@
/* global libopenmpt UTF8ToString writeAsciiToMemory */
// @ts-nocheck
/* eslint-disable */
const ChiptuneAudioContext = window.AudioContext || window.webkitAudioContext;
export function ChiptuneJsConfig (repeatCount: number, context: AudioContext) {
let libopenmpt
let libopenmptLoadPromise
export function ChiptuneJsConfig (repeatCount?: number, context?: AudioContext) {
this.repeatCount = repeatCount;
this.context = context;
}
@ -20,6 +23,28 @@ export function ChiptuneJsPlayer (config: object) {
this.volume = 1;
}
ChiptuneJsPlayer.prototype.initialize = function() {
if (libopenmptLoadPromise) return libopenmptLoadPromise;
if (libopenmpt) return Promise.resolve();
libopenmptLoadPromise = new Promise(async (resolve, reject) => {
try {
const { Module } = await import('./libopenmpt/libopenmpt.js');
await new Promise((resolve) => {
Module['onRuntimeInitialized'] = resolve;
})
libopenmpt = Module;
resolve()
} catch (e) {
reject(e)
} finally {
libopenmptLoadPromise = undefined;
}
})
return libopenmptLoadPromise;
}
ChiptuneJsPlayer.prototype.constructor = ChiptuneJsPlayer;
ChiptuneJsPlayer.prototype.fireEvent = function (eventName: string, response) {
@ -61,12 +86,12 @@ ChiptuneJsPlayer.prototype.seek = function (position: number) {
ChiptuneJsPlayer.prototype.metadata = function () {
const data = {};
const keys = UTF8ToString(libopenmpt._openmpt_module_get_metadata_keys(this.currentPlayingNode.modulePtr)).split(';');
const keys = libopenmpt.UTF8ToString(libopenmpt._openmpt_module_get_metadata_keys(this.currentPlayingNode.modulePtr)).split(';');
let keyNameBuffer = 0;
for (const key of keys) {
keyNameBuffer = libopenmpt._malloc(key.length + 1);
writeAsciiToMemory(key, keyNameBuffer);
data[key] = UTF8ToString(libopenmpt._openmpt_module_get_metadata(this.currentPlayingNode.modulePtr, keyNameBuffer));
libopenmpt.writeAsciiToMemory(key, keyNameBuffer);
data[key] = libopenmpt.UTF8ToString(libopenmpt._openmpt_module_get_metadata(this.currentPlayingNode.modulePtr, keyNameBuffer));
libopenmpt._free(keyNameBuffer);
}
return data;
@ -84,7 +109,7 @@ ChiptuneJsPlayer.prototype.unlock = function () {
};
ChiptuneJsPlayer.prototype.load = function (input) {
return new Promise((resolve, reject) => {
return this.initialize().then(() => new Promise((resolve, reject) => {
if(this.touchLocked) {
this.unlock();
}
@ -106,7 +131,7 @@ ChiptuneJsPlayer.prototype.load = function (input) {
reject(error);
});
}
});
}));
};
ChiptuneJsPlayer.prototype.play = function (buffer: ArrayBuffer) {
@ -180,7 +205,7 @@ ChiptuneJsPlayer.prototype.getPatternNumRows = function (pattern: number) {
ChiptuneJsPlayer.prototype.getPatternRowChannel = function (pattern: number, row: number, channel: number) {
if (this.currentPlayingNode && this.currentPlayingNode.modulePtr) {
return UTF8ToString(libopenmpt._openmpt_module_format_pattern_row_channel(this.currentPlayingNode.modulePtr, pattern, row, channel, 0, true));
return libopenmpt.UTF8ToString(libopenmpt._openmpt_module_format_pattern_row_channel(this.currentPlayingNode.modulePtr, pattern, row, channel, 0, true));
}
return '';
};

View file

@ -0,0 +1,25 @@
Copyright (c) 2004-2024, OpenMPT Project Developers and Contributors
Copyright (c) 1997-2003, Olivier Lapicque
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the OpenMPT project nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,23 @@
modifications made to `libopenmpt.js` (can be taken from https://lib.openmpt.org/libopenmpt/download/):
at the beginning of the file:
```js
// @ts-nocheck
/* eslint-disable */
```
at the end of the file:
```js
Module.UTF8ToString = UTF8ToString;
Module.writeAsciiToMemory = writeAsciiToMemory;
export { Module }
```
replace
```
wasmBinaryFile="libopenmpt.wasm"
```
with
```
wasmBinaryFile=new URL("./libopenmpt.wasm", import.meta.url).href
```

View file

@ -8,7 +8,7 @@ import meta from '../../package.json';
import pluginUnwindCssModuleClassName from './lib/rollup-plugin-unwind-css-module-class-name.js';
import pluginJson5 from './vite.json5.js';
const extensions = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.json', '.json5', '.svg', '.sass', '.scss', '.css', '.vue'];
const extensions = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.json', '.json5', '.svg', '.sass', '.scss', '.css', '.vue', '.wasm'];
const hash = (str: string, seed = 0): number => {
let h1 = 0xdeadbeef ^ seed,

View file

@ -19,6 +19,7 @@ namespace Entity {
content: string
plain_content?: string | null
created_at: string
edited_at: string | null
emojis: Emoji[]
replies_count: number
reblogs_count: number

View file

@ -725,6 +725,7 @@ namespace FriendicaAPI {
content: s.content,
plain_content: null,
created_at: s.created_at,
edited_at: s.edited_at || null,
emojis: Array.isArray(s.emojis) ? s.emojis.map(e => emoji(e)) : [],
replies_count: s.replies_count,
reblogs_count: s.reblogs_count,

View file

@ -17,6 +17,7 @@ namespace FriendicaEntity {
reblog: Status | null
content: string
created_at: string
edited_at?: string | null
emojis: Emoji[]
replies_count: number
reblogs_count: number

View file

@ -628,6 +628,7 @@ namespace MastodonAPI {
content: s.content,
plain_content: null,
created_at: s.created_at,
edited_at: s.edited_at || null,
emojis: Array.isArray(s.emojis) ? s.emojis.map(e => emoji(e)) : [],
replies_count: s.replies_count,
reblogs_count: s.reblogs_count,

View file

@ -18,6 +18,7 @@ namespace MastodonEntity {
reblog: Status | null
content: string
created_at: string
edited_at?: string | null
emojis: Emoji[]
replies_count: number
reblogs_count: number

View file

@ -283,6 +283,7 @@ namespace MisskeyAPI {
: '',
plain_content: n.text ? n.text : null,
created_at: n.createdAt,
edited_at: n.updatedAt || null,
emojis: mapEmojis(n.emojis).concat(mapReactionEmojis(n.reactionEmojis)),
replies_count: n.repliesCount,
reblogs_count: n.renoteCount,

View file

@ -7,6 +7,7 @@ namespace MisskeyEntity {
export type Note = {
id: string
createdAt: string
updatedAt?: string | null
userId: string
user: User
text: string | null

View file

@ -357,6 +357,7 @@ namespace PleromaAPI {
content: s.content,
plain_content: s.pleroma.content?.['text/plain'] ? s.pleroma.content['text/plain'] : null,
created_at: s.created_at,
edited_at: s.edited_at || null,
emojis: Array.isArray(s.emojis) ? s.emojis.map(e => emoji(e)) : [],
replies_count: s.replies_count,
reblogs_count: s.reblogs_count,

View file

@ -18,6 +18,7 @@ namespace PleromaEntity {
reblog: Status | null
content: string
created_at: string
edited_at?: string | null
emojis: Emoji[]
replies_count: number
reblogs_count: number

View file

@ -49,6 +49,7 @@ const status: Entity.Status = {
content: 'hoge',
plain_content: null,
created_at: '2019-03-26T21:40:32',
edited_at: null,
emojis: [],
replies_count: 0,
reblogs_count: 0,

View file

@ -38,6 +38,7 @@ const status: Entity.Status = {
content: 'hoge',
plain_content: 'hoge',
created_at: '2019-03-26T21:40:32',
edited_at: null,
emojis: [],
replies_count: 0,
reblogs_count: 0,

View file

@ -37,6 +37,7 @@ const status: Entity.Status = {
content: 'hoge',
plain_content: 'hoge',
created_at: '2019-03-26T21:40:32',
edited_at: null,
emojis: [],
replies_count: 0,
reblogs_count: 0,

View file

@ -392,8 +392,8 @@ importers:
specifier: 1.6.0
version: 1.6.0
tmp:
specifier: 0.2.2
version: 0.2.2
specifier: 0.2.3
version: 0.2.3
tsc-alias:
specifier: 1.8.8
version: 1.8.8
@ -18813,6 +18813,12 @@ packages:
engines: {node: '>=14'}
dependencies:
rimraf: 5.0.5
dev: true
/tmp@0.2.3:
resolution: {integrity: sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==}
engines: {node: '>=14.14'}
dev: false
/tmpl@1.0.5:
resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==}