Merge branch 'develop' of https://codeberg.org/calckey/calckey into feat/module-player

This commit is contained in:
Essem 2023-07-09 17:31:23 -05:00
commit 1a597edfcb
No known key found for this signature in database
GPG key ID: 7D497397CC3A2A8C
15 changed files with 85 additions and 24 deletions

View file

@ -20,5 +20,11 @@ export function nyaize(text: string): string {
) )
.replace(/(다$)|(다(?=\.))|(다(?= ))|(다(?=!))|(다(?=\?))/gm, "다냥") .replace(/(다$)|(다(?=\.))|(다(?= ))|(다(?=!))|(다(?=\?))/gm, "다냥")
.replace(/(야(?=\?))|(야$)|(야(?= ))/gm, "냥") .replace(/(야(?=\?))|(야$)|(야(?= ))/gm, "냥")
// zh-CN, zh-TW
.replace(/(妙|庙|描|渺|瞄|秒|苗|藐|廟)/g, "喵")
// el-GR
.replaceAll("να", "νια")
.replaceAll("ΝΑ", "ΝΙΑ")
.replaceAll("Να", "Νια")
); );
} }

View file

@ -21,6 +21,7 @@ export const meta = {
message: "No such note.", message: "No such note.",
code: "NO_SUCH_NOTE", code: "NO_SUCH_NOTE",
id: "24fcbfc6-2e37-42b6-8388-c29b3861a08d", id: "24fcbfc6-2e37-42b6-8388-c29b3861a08d",
httpStatusCode: 404,
}, },
}, },
} as const; } as const;

View file

@ -1,4 +1,5 @@
import { Entity } from "megalodon"; import { Entity } from "megalodon";
import config from "@/config/index.js";
import { fetchMeta } from "@/misc/fetch-meta.js"; import { fetchMeta } from "@/misc/fetch-meta.js";
import { Users, Notes } from "@/models/index.js"; import { Users, Notes } from "@/models/index.js";
import { IsNull, MoreThan } from "typeorm"; import { IsNull, MoreThan } from "typeorm";
@ -17,7 +18,7 @@ export async function getInstance(response: Entity.Instance) {
response.description || response.description ||
"This is a vanilla Calckey Instance. It doesnt seem to have a description. BTW you are using the Mastodon api to access this server :)", "This is a vanilla Calckey Instance. It doesnt seem to have a description. BTW you are using the Mastodon api to access this server :)",
email: response.email || "", email: response.email || "",
version: "3.0.0 compatible (3.5+ Calckey)", //I hope this version string is correct, we will need to test it. version: `3.0.0 (compatible; Calckey ${config.version})`,
urls: response.urls, urls: response.urls,
stats: { stats: {
user_count: await totalUsers, user_count: await totalUsers,

View file

@ -67,6 +67,25 @@ export function apiStatusMastodon(router: Router): void {
const { sensitive } = body; const { sensitive } = body;
body.sensitive = body.sensitive =
typeof sensitive === "string" ? sensitive === "true" : sensitive; typeof sensitive === "string" ? sensitive === "true" : sensitive;
if (body.poll) {
if (
body.poll.expires_in != null &&
typeof body.poll.expires_in === "string"
)
body.poll.expires_in = parseInt(body.poll.expires_in);
if (
body.poll.multiple != null &&
typeof body.poll.multiple === "string"
)
body.poll.multiple = body.poll.multiple == "true";
if (
body.poll.hide_totals != null &&
typeof body.poll.hide_totals === "string"
)
body.poll.hide_totals = body.poll.hide_totals == "true";
}
const data = await client.postStatus(text, body); const data = await client.postStatus(text, body);
ctx.body = convertStatus(data.data); ctx.body = convertStatus(data.data);
} catch (e: any) { } catch (e: any) {
@ -86,7 +105,7 @@ export function apiStatusMastodon(router: Router): void {
ctx.body = convertStatus(data.data); ctx.body = convertStatus(data.data);
} catch (e: any) { } catch (e: any) {
console.error(e); console.error(e);
ctx.status = 401; ctx.status = ctx.status == 404 ? 404 : 401;
ctx.body = e.response.data; ctx.body = e.response.data;
} }
}); });

View file

@ -196,6 +196,7 @@ onUnmounted(() => {
> a { > a {
display: flex; display: flex;
transition: background 0.2s; transition: background 0.2s;
text-decoration: none;
> div:first-child:not(:last-child) { > div:first-child:not(:last-child) {
position: relative; position: relative;
width: 90px; width: 90px;
@ -277,7 +278,7 @@ onUnmounted(() => {
&:focus, &:focus,
&:focus-within { &:focus-within {
background: var(--panelHighlight); background: var(--panelHighlight);
h1 { h3 {
text-decoration: underline; text-decoration: underline;
} }
} }

View file

@ -80,6 +80,8 @@ const target = self ? null : "_blank";
display: inline-block; display: inline-block;
overflow: clip; overflow: clip;
text-overflow: ellipsis; text-overflow: ellipsis;
text-decoration: none !important;
line-height: 1.05;
> .icon { > .icon {
padding-left: 2px; padding-left: 2px;

View file

@ -409,6 +409,7 @@ export default defineComponent({
key: Math.random(), key: Math.random(),
to: `/tags/${encodeURIComponent(token.props.hashtag)}`, to: `/tags/${encodeURIComponent(token.props.hashtag)}`,
style: "color:var(--hashtag);", style: "color:var(--hashtag);",
class: "_link",
}, },
`#${token.props.hashtag}`, `#${token.props.hashtag}`,
), ),

View file

@ -145,6 +145,9 @@ a {
cursor: pointer; cursor: pointer;
color: inherit; color: inherit;
-webkit-tap-highlight-color: transparent; -webkit-tap-highlight-color: transparent;
&:hover {
text-decoration: underline;
}
} }
// i { // i {
@ -229,6 +232,7 @@ hr {
font-size: 1em; font-size: 1em;
font-family: inherit; font-family: inherit;
line-height: inherit; line-height: inherit;
text-decoration: none;
&, &,
* { * {
@ -628,18 +632,22 @@ hr {
._link { ._link {
position: relative; position: relative;
color: var(--link); color: var(--link);
text-decoration: none !important;
&:after { &::before, &::after {
content: ""; content: "";
position: absolute; position: absolute;
bottom: 0; bottom: 0;
left: 0; left: 0;
width: 0%; width: 0%;
border-bottom: 2px solid var(--link); border-bottom: 1px solid var(--link);
transition: 0.3s ease-in-out; transition: 0.3s ease-in-out;
} }
&::before {
&:hover:after { width: 100%;
opacity: .4;
}
&:hover:after, &:focus:after {
width: 100%; width: 100%;
} }
} }

View file

@ -408,7 +408,7 @@ export default class Misskey implements MegalodonInterface {
if (options) { if (options) {
if (options.limit) { if (options.limit) {
params = Object.assign(params, { params = Object.assign(params, {
limit: options.limit limit: options.limit <= 100 ? options.limit : 100
}) })
} }
if (options.max_id) { if (options.max_id) {
@ -738,7 +738,7 @@ export default class Misskey implements MegalodonInterface {
if (options) { if (options) {
if (options.limit) { if (options.limit) {
params = Object.assign(params, { params = Object.assign(params, {
limit: options.limit limit: options.limit <= 100 ? options.limit : 100
}) })
} }
else { else {
@ -1169,7 +1169,7 @@ export default class Misskey implements MegalodonInterface {
let pollParam = { let pollParam = {
choices: options.poll.options, choices: options.poll.options,
expiresAt: null, expiresAt: null,
expiredAfter: options.poll.expires_in expiredAfter: options.poll.expires_in * 1000
} }
if (options.poll.multiple !== undefined) { if (options.poll.multiple !== undefined) {
pollParam = Object.assign(pollParam, { pollParam = Object.assign(pollParam, {
@ -1236,14 +1236,24 @@ export default class Misskey implements MegalodonInterface {
const notification = this.converter.notification(n, host); const notification = this.converter.notification(n, host);
if (n.note) if (n.note)
notification.status = await this.noteWithDetails(n.note, host, cache); notification.status = await this.noteWithDetails(n.note, host, cache);
if (notification.account)
notification.account = (await this.getAccount(notification.account.id)).data
return notification; return notification;
} }
public async noteWithDetails(n: MisskeyAPI.Entity.Note, host: string, cache: AccountCache): Promise<MegalodonEntity.Status> { public async noteWithDetails(n: MisskeyAPI.Entity.Note, host: string, cache: AccountCache): Promise<MegalodonEntity.Status> {
const status = await this.addUserDetailsToStatus(this.converter.note(n, host), cache); const status = await this.addUserDetailsToStatus(this.converter.note(n, host), cache);
status.bookmarked = await this.isStatusBookmarked(n.id);
return this.addMentionsToStatus(status, cache); return this.addMentionsToStatus(status, cache);
} }
public async isStatusBookmarked(id: string) : Promise<boolean> {
return this.client
.post<MisskeyAPI.Entity.State>('/api/notes/state', {
noteId: id
}).then(p => p.data.isFavorited ?? false);
}
public async addUserDetailsToStatus(status: Entity.Status, cache: AccountCache) : Promise<Entity.Status> { public async addUserDetailsToStatus(status: Entity.Status, cache: AccountCache) : Promise<Entity.Status> {
if (status.account.followers_count === 0 && status.account.followers_count === 0 && status.account.statuses_count === 0) if (status.account.followers_count === 0 && status.account.followers_count === 0 && status.account.statuses_count === 0)
status.account = await this.getAccountCached(status.account.id, status.account.acct, cache) ?? status.account; status.account = await this.getAccountCached(status.account.id, status.account.acct, cache) ?? status.account;

View file

@ -40,7 +40,8 @@ namespace MisskeyAPI {
export type GetAll = MisskeyEntity.GetAll export type GetAll = MisskeyEntity.GetAll
export type UserKey = MisskeyEntity.UserKey export type UserKey = MisskeyEntity.UserKey
export type Session = MisskeyEntity.Session export type Session = MisskeyEntity.Session
export type Stats = MisskeyEntity.Stats export type Stats = MisskeyEntity.Stats
export type State = MisskeyEntity.State
export type APIEmoji = { emojis: Emoji[] } export type APIEmoji = { emojis: Emoji[] }
} }
@ -396,8 +397,8 @@ namespace MisskeyAPI {
return MisskeyNotificationType.Reaction return MisskeyNotificationType.Reaction
case NotificationType.Reblog: case NotificationType.Reblog:
return MisskeyNotificationType.Renote return MisskeyNotificationType.Renote
case NotificationType.PollVote: case NotificationType.Poll:
return MisskeyNotificationType.PollVote return MisskeyNotificationType.PollEnded
case NotificationType.FollowRequest: case NotificationType.FollowRequest:
return MisskeyNotificationType.ReceiveFollowRequest return MisskeyNotificationType.ReceiveFollowRequest
default: default:
@ -417,8 +418,8 @@ namespace MisskeyAPI {
return NotificationType.Reblog return NotificationType.Reblog
case MisskeyNotificationType.Reaction: case MisskeyNotificationType.Reaction:
return NotificationType.EmojiReaction return NotificationType.EmojiReaction
case MisskeyNotificationType.PollVote: case MisskeyNotificationType.PollEnded:
return NotificationType.PollVote return NotificationType.Poll
case MisskeyNotificationType.ReceiveFollowRequest: case MisskeyNotificationType.ReceiveFollowRequest:
return NotificationType.FollowRequest return NotificationType.FollowRequest
case MisskeyNotificationType.FollowRequestAccepted: case MisskeyNotificationType.FollowRequestAccepted:
@ -458,6 +459,11 @@ namespace MisskeyAPI {
notification = Object.assign(notification, { notification = Object.assign(notification, {
status: this.note(n.note, host) status: this.note(n.note, host)
}) })
if (notification.type === NotificationType.Poll) {
notification = Object.assign(notification, {
account: this.note(n.note, host).account
})
}
} }
if (n.reaction) { if (n.reaction) {
notification = Object.assign(notification, { notification = Object.assign(notification, {

View file

@ -0,0 +1,7 @@
namespace MisskeyEntity {
export type State = {
isFavorited: boolean
isMutedThread: boolean
isWatching: boolean
}
}

View file

@ -7,7 +7,7 @@ namespace MisskeyNotificationType {
export const Renote: MisskeyEntity.NotificationType = 'renote' export const Renote: MisskeyEntity.NotificationType = 'renote'
export const Quote: MisskeyEntity.NotificationType = 'quote' export const Quote: MisskeyEntity.NotificationType = 'quote'
export const Reaction: MisskeyEntity.NotificationType = 'favourite' export const Reaction: MisskeyEntity.NotificationType = 'favourite'
export const PollVote: MisskeyEntity.NotificationType = 'pollVote' export const PollEnded: MisskeyEntity.NotificationType = 'pollEnded'
export const ReceiveFollowRequest: MisskeyEntity.NotificationType = 'receiveFollowRequest' export const ReceiveFollowRequest: MisskeyEntity.NotificationType = 'receiveFollowRequest'
export const FollowRequestAccepted: MisskeyEntity.NotificationType = 'followRequestAccepted' export const FollowRequestAccepted: MisskeyEntity.NotificationType = 'followRequestAccepted'
export const GroupInvited: MisskeyEntity.NotificationType = 'groupInvited' export const GroupInvited: MisskeyEntity.NotificationType = 'groupInvited'

View file

@ -8,8 +8,7 @@ namespace NotificationType {
export const EmojiReaction: Entity.NotificationType = 'emoji_reaction' export const EmojiReaction: Entity.NotificationType = 'emoji_reaction'
export const FollowRequest: Entity.NotificationType = 'follow_request' export const FollowRequest: Entity.NotificationType = 'follow_request'
export const Status: Entity.NotificationType = 'status' export const Status: Entity.NotificationType = 'status'
export const PollVote: Entity.NotificationType = 'poll_vote' export const Poll: Entity.NotificationType = 'poll'
export const PollExpired: Entity.NotificationType = 'poll_expired'
} }
export default NotificationType export default NotificationType

View file

@ -93,7 +93,7 @@ const pollVote: MisskeyEntity.Notification = {
createdAt: '2021-02-01T01:49:29', createdAt: '2021-02-01T01:49:29',
userId: user.id, userId: user.id,
user: user, user: user,
type: MisskeyNotificationType.PollVote, type: MisskeyNotificationType.PollEnded,
note: note note: note
} }
@ -168,7 +168,7 @@ describe('getNotifications', () => {
}, },
{ {
event: pollVote, event: pollVote,
expected: MegalodonNotificationType.PollVote, expected: MegalodonNotificationType.Poll,
title: 'pollVote' title: 'pollVote'
}, },
{ {

View file

@ -42,8 +42,8 @@ describe('api_client', () => {
dist: MisskeyNotificationType.Renote dist: MisskeyNotificationType.Renote
}, },
{ {
src: MegalodonNotificationType.PollVote, src: MegalodonNotificationType.Poll,
dist: MisskeyNotificationType.PollVote dist: MisskeyNotificationType.PollEnded
}, },
{ {
src: MegalodonNotificationType.FollowRequest, src: MegalodonNotificationType.FollowRequest,
@ -83,8 +83,8 @@ describe('api_client', () => {
dist: MegalodonNotificationType.EmojiReaction dist: MegalodonNotificationType.EmojiReaction
}, },
{ {
src: MisskeyNotificationType.PollVote, src: MisskeyNotificationType.PollEnded,
dist: MegalodonNotificationType.PollVote dist: MegalodonNotificationType.Poll
}, },
{ {
src: MisskeyNotificationType.ReceiveFollowRequest, src: MisskeyNotificationType.ReceiveFollowRequest,