Merge branch 'develop' of https://codeberg.org/calckey/calckey into feat/module-player
This commit is contained in:
commit
1a597edfcb
15 changed files with 85 additions and 24 deletions
|
@ -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("Να", "Νια")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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}`,
|
||||||
),
|
),
|
||||||
|
|
|
@ -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%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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, {
|
||||||
|
|
7
packages/megalodon/src/misskey/entities/state.ts
Normal file
7
packages/megalodon/src/misskey/entities/state.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
namespace MisskeyEntity {
|
||||||
|
export type State = {
|
||||||
|
isFavorited: boolean
|
||||||
|
isMutedThread: boolean
|
||||||
|
isWatching: boolean
|
||||||
|
}
|
||||||
|
}
|
|
@ -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'
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in a new issue