Skip to content
This repository has been archived by the owner on Jan 31, 2024. It is now read-only.

Merge Beta3 #34

Merged
merged 32 commits into from
Oct 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
277fa87
test: fix font
Insert5StarName Sep 30, 2023
9557274
Merge pull request #26 from transfem-org/test/fixfont
Insert5StarName Sep 30, 2023
2b4e9e5
upd: remove overscroll
Sep 30, 2023
00c14b9
upd: fix defaults, make people happy
Sep 30, 2023
f2e299a
upd: change icon font
Sep 30, 2023
7b179d3
work in progress icons
Sep 30, 2023
b50c1ef
upd: fix rest of icons
Sep 30, 2023
687c33c
upd: looks better than small circle
Sep 30, 2023
2ea7e79
upd: add buttons to replies
Sep 30, 2023
8d4e99b
Merge branch 'icons' of https://github.com/transfem-org/Sharkey into …
Sep 30, 2023
b2ae28e
fix: how tf did this happen
Sep 30, 2023
a782aa5
fix: more sane defaults
Sep 30, 2023
7a51e2d
prototype: decreased rounding
Sep 30, 2023
cbb7bf1
test: Merge UI and Icon Changes
Insert5StarName Sep 30, 2023
9c8aaf3
test: change buttons and avatar
Sep 30, 2023
3428dbf
fix: link find instances
Sep 30, 2023
b64f963
Merge pull request #31 from transfem-org/icons
Insert5StarName Sep 30, 2023
802ad0f
add: like button
Sep 30, 2023
9fd66f9
Merge branch 'icons' of https://github.com/transfem-org/Sharkey into …
Sep 30, 2023
e5d9eb3
merge: add like button #32
Sep 30, 2023
54578f6
upd: add MFM to HTML support and Mentions parsing to mastodon api (#33)
Sep 30, 2023
e0fd136
fix: css rounding
Oct 1, 2023
099b86f
chore: lint
Oct 1, 2023
ae3d77a
Merge branch 'develop' of https://github.com/transfem-org/Sharkey int…
Oct 1, 2023
f82f2cc
upd: add like button to normal note component
Oct 1, 2023
ba4ab40
fix: like button class
Oct 1, 2023
c270d81
fix: enable animated mfm by default
Oct 1, 2023
6a9e6a7
chore: update version
Oct 1, 2023
3d8414e
fix: like button opening post view, remove tabler
Oct 1, 2023
8673435
fix: css rounding in nav
Oct 1, 2023
e92137e
fix: minus button
Oct 1, 2023
a67810c
Merge branch 'develop' of https://github.com/transfem-org/Sharkey int…
Oct 1, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 6 additions & 0 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
name: Publish Docker image

on:
push:
branches:
- stable
paths:
- packages/**
- locales/**
release:
types: [published]
workflow_dispatch:
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "sharkey",
"version": "2023.9.1.beta2",
"version": "2023.9.1.beta3",
"codename": "shonk",
"repository": {
"type": "git",
Expand Down
Binary file added packages/backend/assets/transparent.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 3 additions & 4 deletions packages/backend/src/core/entities/NoteEntityService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,9 @@ export class NoteEntityService implements OnModuleInit {
uri: note.uri ?? undefined,
url: note.url ?? undefined,
updatedAt: note.updatedAt != null ? note.updatedAt.toISOString() : undefined,
...(meId ? {
myReaction: this.populateMyReaction(note, meId, options?._hint_),
} : {}),

...(opts.detail ? {
clippedCount: note.clippedCount,
Expand All @@ -358,10 +361,6 @@ export class NoteEntityService implements OnModuleInit {
}) : undefined,

poll: note.hasPoll ? this.populatePoll(note, meId) : undefined,

...(meId ? {
myReaction: this.populateMyReaction(note, meId, options?._hint_),
} : {}),
} : {}),
});

Expand Down
2 changes: 1 addition & 1 deletion packages/backend/src/server/api/endpoints/ap/show.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const meta = {
requireCredential: true,

limit: {
duration: ms('1hour'),
duration: ms('1minute'),
max: 30,
},

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import megalodon, { Entity, MegalodonInterface } from 'megalodon';
import querystring from 'querystring';
import { IsNull } from 'typeorm';
import multer from 'fastify-multer';
import type { UsersRepository } from '@/models/_.js';
import type { NotesRepository, UserProfilesRepository, UsersRepository } from '@/models/_.js';
import { DI } from '@/di-symbols.js';
import { bindThis } from '@/decorators.js';
import type { Config } from '@/config.js';
Expand All @@ -12,6 +12,7 @@ import { convertId, IdConvertType as IdType, convertAccount, convertAnnouncement
import { getInstance } from './endpoints/meta.js';
import { ApiAuthMastodon, ApiAccountMastodon, ApiFilterMastodon, ApiNotifyMastodon, ApiSearchMastodon, ApiTimelineMastodon, ApiStatusMastodon } from './endpoints.js';
import type { FastifyInstance, FastifyPluginOptions } from 'fastify';
import { UserEntityService } from '@/core/entities/UserEntityService.js';

export function getClient(BASE_URL: string, authorization: string | undefined): MegalodonInterface {
const accessTokenArr = authorization?.split(' ') ?? [null];
Expand All @@ -26,9 +27,14 @@ export class MastodonApiServerService {
constructor(
@Inject(DI.usersRepository)
private usersRepository: UsersRepository,
@Inject(DI.notesRepository)
private notesRepository: NotesRepository,
@Inject(DI.userProfilesRepository)
private userProfilesRepository: UserProfilesRepository,
@Inject(DI.config)
private config: Config,
private metaService: MetaService,
private userEntityService: UserEntityService,
) { }

@bindThis
Expand Down Expand Up @@ -256,8 +262,10 @@ export class MastodonApiServerService {
const client = getClient(BASE_URL, accessTokens); // we are using this here, because in private mode some info isnt
// displayed without being logged in
try {
const account = new ApiAccountMastodon(_request, client, BASE_URL);
reply.send(await account.lookup());
const data = await client.search((_request.query as any).acct, { type: 'accounts' });
const profile = await this.userProfilesRepository.findOneBy({ userId: data.data.accounts[0].id });
data.data.accounts[0].fields = profile?.fields.map(f => ({ ...f, verified_at: null })) || [];
reply.send(convertAccount(data.data.accounts[0]));
} catch (e: any) {
/* console.error(e); */
reply.code(401).send(e.response.data);
Expand Down Expand Up @@ -294,6 +302,8 @@ export class MastodonApiServerService {
try {
const sharkId = convertId(_request.params.id, IdType.SharkeyId);
const data = await client.getAccount(sharkId);
const profile = await this.userProfilesRepository.findOneBy({ userId: sharkId });
data.data.fields = profile?.fields.map(f => ({ ...f, verified_at: null })) || [];
reply.send(convertAccount(data.data));
} catch (e: any) {
/* console.error(e);
Expand Down Expand Up @@ -744,7 +754,7 @@ export class MastodonApiServerService {
//#endregion

//#region Timelines
const TLEndpoint = new ApiTimelineMastodon(fastify);
const TLEndpoint = new ApiTimelineMastodon(fastify, this.config, this.usersRepository, this.notesRepository, this.userEntityService);

// GET Endpoints
TLEndpoint.getTL();
Expand All @@ -769,7 +779,7 @@ export class MastodonApiServerService {
//#endregion

//#region Status
const NoteEndpoint = new ApiStatusMastodon(fastify);
const NoteEndpoint = new ApiStatusMastodon(fastify, this.config, this.usersRepository, this.notesRepository, this.userEntityService);

// GET Endpoints
NoteEndpoint.getStatus();
Expand Down
95 changes: 95 additions & 0 deletions packages/backend/src/server/api/mastodon/converters.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
import type { Config } from '@/config.js';
import { MfmService } from '@/core/MfmService.js';
import { DI } from '@/di-symbols.js';
import { Inject } from '@nestjs/common';
import { Entity } from 'megalodon';
import { parse } from 'mfm-js';
import { GetterService } from '../GetterService.js';
import type { IMentionedRemoteUsers } from '@/models/Note.js';
import type { MiUser } from '@/models/User.js';
import type { NotesRepository, UsersRepository } from '@/models/_.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js';

const CHAR_COLLECTION = '0123456789abcdefghijklmnopqrstuvwxyz';

Expand All @@ -7,6 +17,91 @@ export enum IdConvertType {
SharkeyId,
}

export const escapeMFM = (text: string): string => text
.replace(/&/g, "&")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#39;")
.replace(/`/g, "&#x60;")
.replace(/\r?\n/g, "<br>");

export class MastoConverters {
private MfmService: MfmService;
private GetterService: GetterService;

constructor(
@Inject(DI.config)
private config: Config,

@Inject(DI.usersRepository)
private usersRepository: UsersRepository,

@Inject(DI.notesRepository)
private notesRepository: NotesRepository,

private userEntityService: UserEntityService
) {
this.MfmService = new MfmService(this.config);
this.GetterService = new GetterService(this.usersRepository, this.notesRepository, this.userEntityService);
}

private encode(u: MiUser, m: IMentionedRemoteUsers): MastodonEntity.Mention {
let acct = u.username;
let acctUrl = `https://${u.host || this.config.host}/@${u.username}`;
let url: string | null = null;
if (u.host) {
const info = m.find(r => r.username === u.username && r.host === u.host);
acct = `${u.username}@${u.host}`;
acctUrl = `https://${u.host}/@${u.username}`;
if (info) url = info.url ?? info.uri;
}
return {
id: u.id,
username: u.username,
acct: acct,
url: url ?? acctUrl,
};
}

public async getUser(id: string): Promise<MiUser> {
return this.GetterService.getUser(id).then(p => {
return p;
});
}

public async convertStatus(status: Entity.Status) {
status.account = convertAccount(status.account);
const note = await this.GetterService.getNote(status.id);
status.id = convertId(status.id, IdConvertType.MastodonId);
if (status.in_reply_to_account_id) status.in_reply_to_account_id = convertId(
status.in_reply_to_account_id,
IdConvertType.MastodonId,
);
if (status.in_reply_to_id) status.in_reply_to_id = convertId(status.in_reply_to_id, IdConvertType.MastodonId);
status.media_attachments = status.media_attachments.map((attachment) =>
convertAttachment(attachment),
);
// This will eventually be improved with a rewrite of this file
const mentions = Promise.all(note.mentions.map(p =>
this.getUser(p)
.then(u => this.encode(u, JSON.parse(note.mentionedRemoteUsers)))
.catch(() => null)))
.then(p => p.filter(m => m)) as Promise<MastodonEntity.Mention[]>;
status.mentions = await mentions;
status.mentions = status.mentions.map((mention) => ({
...mention,
id: convertId(mention.id, IdConvertType.MastodonId),
}));
const convertedMFM = this.MfmService.toHtml(parse(status.content), JSON.parse(note.mentionedRemoteUsers));
status.content = status.content ? convertedMFM?.replace(/&amp;/g, "&").replaceAll(`<span>&</span><a href="${this.config.url}/tags/39;" rel="tag">#39;</a>`, "<span>\'</span>") as string : status.content;
if (status.poll) status.poll = convertPoll(status.poll);
if (status.reblog) status.reblog = convertStatus(status.reblog);

return status;
}
}

export function convertId(in_id: string, id_convert_type: IdConvertType): string {
switch (id_convert_type) {
case IdConvertType.MastodonId: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export class ApiAccountMastodon {
const data = await this.client.search((this.request.query as any).acct, { type: 'accounts' });
return convertAccount(data.data.accounts[0]);
} catch (e: any) {
/* console.error(e);
/* console.error(e)
console.error(e.response.data); */
return e.response;
}
Expand Down
39 changes: 22 additions & 17 deletions packages/backend/src/server/api/mastodon/endpoints/status.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import querystring from 'querystring';
import { emojiRegexAtStartToEnd } from '@/misc/emoji-regex.js';
import { convertId, IdConvertType as IdType, convertAccount, convertAttachment, convertPoll, convertStatus, convertStatusSource } from '../converters.js';
import { convertId, IdConvertType as IdType, convertAccount, convertAttachment, convertPoll, convertStatusSource, MastoConverters } from '../converters.js';
import { getClient } from '../MastodonApiServerService.js';
import { convertTimelinesArgsId, limitToInt } from './timeline.js';
import type { Entity } from 'megalodon';
import type { FastifyInstance } from 'fastify';
import type { Config } from '@/config.js';
import { NotesRepository, UsersRepository } from '@/models/_.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js';

function normalizeQuery(data: any) {
const str = querystring.stringify(data);
Expand All @@ -13,9 +16,11 @@ function normalizeQuery(data: any) {

export class ApiStatusMastodon {
private fastify: FastifyInstance;
private mastoconverter: MastoConverters;

constructor(fastify: FastifyInstance) {
constructor(fastify: FastifyInstance, config: Config, usersrepo: UsersRepository, notesrepo: NotesRepository, userentity: UserEntityService) {
this.fastify = fastify;
this.mastoconverter = new MastoConverters(config, usersrepo, notesrepo, userentity);
}

public async getStatus() {
Expand All @@ -25,7 +30,7 @@ export class ApiStatusMastodon {
const client = getClient(BASE_URL, accessTokens);
try {
const data = await client.getStatus(convertId(_request.params.id, IdType.SharkeyId));
reply.send(convertStatus(data.data));
reply.send(await this.mastoconverter.convertStatus(data.data));
} catch (e: any) {
console.error(e);
reply.code(_request.is404 ? 404 : 401).send(e.response.data);
Expand Down Expand Up @@ -59,8 +64,8 @@ export class ApiStatusMastodon {
convertId(_request.params.id, IdType.SharkeyId),
convertTimelinesArgsId(limitToInt(query)),
);
data.data.ancestors = data.data.ancestors.map((status: Entity.Status) => convertStatus(status));
data.data.descendants = data.data.descendants.map((status: Entity.Status) => convertStatus(status));
data.data.ancestors = await Promise.all(data.data.ancestors.map(async (status: Entity.Status) => await this.mastoconverter.convertStatus(status)));
data.data.descendants = await Promise.all(data.data.descendants.map(async (status: Entity.Status) => await this.mastoconverter.convertStatus(status)));
reply.send(data.data);
} catch (e: any) {
console.error(e);
Expand Down Expand Up @@ -219,7 +224,7 @@ export class ApiStatusMastodon {
}

const data = await client.postStatus(text, body);
reply.send(convertStatus(data.data as Entity.Status));
reply.send(await this.mastoconverter.convertStatus(data.data as Entity.Status));
} catch (e: any) {
console.error(e);
reply.code(401).send(e.response.data);
Expand All @@ -240,7 +245,7 @@ export class ApiStatusMastodon {
body.media_ids = (body.media_ids as string[]).map((p) => convertId(p, IdType.SharkeyId));
}
const data = await client.editStatus(convertId(_request.params.id, IdType.SharkeyId), body);
reply.send(convertStatus(data.data));
reply.send(await this.mastoconverter.convertStatus(data.data));
} catch (e: any) {
console.error(e);
reply.code(_request.is404 ? 404 : 401).send(e.response.data);
Expand All @@ -258,7 +263,7 @@ export class ApiStatusMastodon {
convertId(_request.params.id, IdType.SharkeyId),
'❤',
)) as any;
reply.send(convertStatus(data.data));
reply.send(await this.mastoconverter.convertStatus(data.data));
} catch (e: any) {
console.error(e);
reply.code(401).send(e.response.data);
Expand All @@ -276,7 +281,7 @@ export class ApiStatusMastodon {
convertId(_request.params.id, IdType.SharkeyId),
'❤',
);
reply.send(convertStatus(data.data));
reply.send(await this.mastoconverter.convertStatus(data.data));
} catch (e: any) {
console.error(e);
reply.code(401).send(e.response.data);
Expand All @@ -291,7 +296,7 @@ export class ApiStatusMastodon {
const client = getClient(BASE_URL, accessTokens);
try {
const data = await client.reblogStatus(convertId(_request.params.id, IdType.SharkeyId));
reply.send(convertStatus(data.data));
reply.send(await this.mastoconverter.convertStatus(data.data));
} catch (e: any) {
console.error(e);
reply.code(401).send(e.response.data);
Expand All @@ -306,7 +311,7 @@ export class ApiStatusMastodon {
const client = getClient(BASE_URL, accessTokens);
try {
const data = await client.unreblogStatus(convertId(_request.params.id, IdType.SharkeyId));
reply.send(convertStatus(data.data));
reply.send(await this.mastoconverter.convertStatus(data.data));
} catch (e: any) {
console.error(e);
reply.code(401).send(e.response.data);
Expand All @@ -321,7 +326,7 @@ export class ApiStatusMastodon {
const client = getClient(BASE_URL, accessTokens);
try {
const data = await client.bookmarkStatus(convertId(_request.params.id, IdType.SharkeyId));
reply.send(convertStatus(data.data));
reply.send(await this.mastoconverter.convertStatus(data.data));
} catch (e: any) {
console.error(e);
reply.code(401).send(e.response.data);
Expand All @@ -336,7 +341,7 @@ export class ApiStatusMastodon {
const client = getClient(BASE_URL, accessTokens);
try {
const data = await client.unbookmarkStatus(convertId(_request.params.id, IdType.SharkeyId));
reply.send(convertStatus(data.data));
reply.send(await this.mastoconverter.convertStatus(data.data));
} catch (e: any) {
console.error(e);
reply.code(401).send(e.response.data);
Expand All @@ -351,7 +356,7 @@ export class ApiStatusMastodon {
const client = getClient(BASE_URL, accessTokens);
try {
const data = await client.pinStatus(convertId(_request.params.id, IdType.SharkeyId));
reply.send(convertStatus(data.data));
reply.send(await this.mastoconverter.convertStatus(data.data));
} catch (e: any) {
console.error(e);
reply.code(401).send(e.response.data);
Expand All @@ -366,7 +371,7 @@ export class ApiStatusMastodon {
const client = getClient(BASE_URL, accessTokens);
try {
const data = await client.unpinStatus(convertId(_request.params.id, IdType.SharkeyId));
reply.send(convertStatus(data.data));
reply.send(await this.mastoconverter.convertStatus(data.data));
} catch (e: any) {
console.error(e);
reply.code(401).send(e.response.data);
Expand All @@ -381,7 +386,7 @@ export class ApiStatusMastodon {
const client = getClient(BASE_URL, accessTokens);
try {
const data = await client.createEmojiReaction(convertId(_request.params.id, IdType.SharkeyId), _request.params.name);
reply.send(convertStatus(data.data));
reply.send(await this.mastoconverter.convertStatus(data.data));
} catch (e: any) {
console.error(e);
reply.code(401).send(e.response.data);
Expand All @@ -396,7 +401,7 @@ export class ApiStatusMastodon {
const client = getClient(BASE_URL, accessTokens);
try {
const data = await client.deleteEmojiReaction(convertId(_request.params.id, IdType.SharkeyId), _request.params.name);
reply.send(convertStatus(data.data));
reply.send(await this.mastoconverter.convertStatus(data.data));
} catch (e: any) {
console.error(e);
reply.code(401).send(e.response.data);
Expand Down
Loading