Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
50e917d232 | |||
ccd14e0462 | |||
d0c0104546 | |||
cd34ade638 | |||
3f91e33a8c | |||
17cc996288 | |||
385776dc0f | |||
e52278c371 | |||
7ffc8c1eda | |||
1359615c82 | |||
7a7a56940c |
@ -15,7 +15,8 @@ jobs:
|
||||
executor: docker
|
||||
steps:
|
||||
- checkout
|
||||
- setup_remote_docker
|
||||
- setup_remote_docker:
|
||||
version: 19.03.13
|
||||
- run:
|
||||
name: Build
|
||||
command: |
|
||||
|
@ -609,6 +609,8 @@ desktop: "デスクトップ"
|
||||
clip: "クリップ"
|
||||
createNew: "新規作成"
|
||||
optional: "任意"
|
||||
createNewClip: "新しいクリップを作成"
|
||||
public: "パブリック"
|
||||
|
||||
_mfm:
|
||||
cheatSheet: "MFMチートシート"
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "misskey",
|
||||
"author": "syuilo <syuilotan@yahoo.co.jp>",
|
||||
"version": "12.57.0",
|
||||
"version": "12.57.4",
|
||||
"codename": "indigo",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -786,7 +786,8 @@ export default defineComponent({
|
||||
},
|
||||
isPublic: {
|
||||
type: 'boolean',
|
||||
label: this.$t('public')
|
||||
label: this.$t('public'),
|
||||
default: false
|
||||
}
|
||||
});
|
||||
if (canceled) return;
|
||||
|
@ -60,7 +60,8 @@ export default defineComponent({
|
||||
},
|
||||
isPublic: {
|
||||
type: 'boolean',
|
||||
label: this.$t('public')
|
||||
label: this.$t('public'),
|
||||
default: false
|
||||
}
|
||||
});
|
||||
if (canceled) return;
|
||||
|
@ -10,7 +10,7 @@ import { ApiError } from '../../error';
|
||||
export const meta = {
|
||||
tags: ['account', 'notes', 'clips'],
|
||||
|
||||
requireCredential: true as const,
|
||||
requireCredential: false as const,
|
||||
|
||||
kind: 'read:account',
|
||||
|
||||
@ -45,13 +45,16 @@ export const meta = {
|
||||
export default define(meta, async (ps, user) => {
|
||||
const clip = await Clips.findOne({
|
||||
id: ps.clipId,
|
||||
userId: user.id
|
||||
});
|
||||
|
||||
if (clip == null) {
|
||||
throw new ApiError(meta.errors.noSuchClip);
|
||||
}
|
||||
|
||||
if (!clip.isPublic && (user == null || (clip.userId !== user.id))) {
|
||||
throw new ApiError(meta.errors.noSuchClip);
|
||||
}
|
||||
|
||||
const clipQuery = ClipNotes.createQueryBuilder('joining')
|
||||
.select('joining.noteId')
|
||||
.where('joining.clipId = :clipId', { clipId: clip.id });
|
||||
@ -61,8 +64,10 @@ export default define(meta, async (ps, user) => {
|
||||
.leftJoinAndSelect('note.user', 'user')
|
||||
.setParameters(clipQuery.getParameters());
|
||||
|
||||
generateVisibilityQuery(query, user);
|
||||
generateMutedUserQuery(query, user);
|
||||
if (user) {
|
||||
generateVisibilityQuery(query, user);
|
||||
generateMutedUserQuery(query, user);
|
||||
}
|
||||
|
||||
const notes = await query
|
||||
.take(ps.limit!)
|
||||
|
@ -7,7 +7,7 @@ import { Clips } from '../../../../models';
|
||||
export const meta = {
|
||||
tags: ['clips', 'account'],
|
||||
|
||||
requireCredential: true as const,
|
||||
requireCredential: false as const,
|
||||
|
||||
kind: 'read:account',
|
||||
|
||||
@ -30,12 +30,15 @@ export default define(meta, async (ps, me) => {
|
||||
// Fetch the clip
|
||||
const clip = await Clips.findOne({
|
||||
id: ps.clipId,
|
||||
userId: me.id,
|
||||
});
|
||||
|
||||
if (clip == null) {
|
||||
throw new ApiError(meta.errors.noSuchClip);
|
||||
}
|
||||
|
||||
if (!clip.isPublic && (me == null || (clip.userId !== me.id))) {
|
||||
throw new ApiError(meta.errors.noSuchClip);
|
||||
}
|
||||
|
||||
return await Clips.pack(clip);
|
||||
});
|
||||
|
@ -17,7 +17,7 @@ import packFeed from './feed';
|
||||
import { fetchMeta } from '../../misc/fetch-meta';
|
||||
import { genOpenapiSpec } from '../api/openapi/gen-spec';
|
||||
import config from '../../config';
|
||||
import { Users, Notes, Emojis, UserProfiles, Pages, Channels } from '../../models';
|
||||
import { Users, Notes, Emojis, UserProfiles, Pages, Channels, Clips } from '../../models';
|
||||
import parseAcct from '../../misc/acct/parse';
|
||||
import getNoteSummary from '../../misc/get-note-summary';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
@ -298,6 +298,28 @@ router.get('/@:user/pages/:page', async ctx => {
|
||||
ctx.status = 404;
|
||||
});
|
||||
|
||||
// Clip
|
||||
router.get('/clips/:clip', async ctx => {
|
||||
const clip = await Clips.findOne({
|
||||
id: ctx.params.clip,
|
||||
});
|
||||
|
||||
if (clip) {
|
||||
const _clip = await Clips.pack(clip);
|
||||
const meta = await fetchMeta();
|
||||
await ctx.render('clip', {
|
||||
clip: _clip,
|
||||
instanceName: meta.name || 'Misskey'
|
||||
});
|
||||
|
||||
ctx.set('Cache-Control', 'public, max-age=180');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ctx.status = 404;
|
||||
});
|
||||
|
||||
// Channel
|
||||
router.get('/channels/:channel', async ctx => {
|
||||
const channel = await Channels.findOne({
|
||||
|
30
src/server/web/views/clip.pug
Normal file
30
src/server/web/views/clip.pug
Normal file
@ -0,0 +1,30 @@
|
||||
extends ./base
|
||||
|
||||
block vars
|
||||
- const user = clip.user;
|
||||
- const title = clip.name;
|
||||
- const url = `${config.url}/clips/${clip.id}`;
|
||||
|
||||
block title
|
||||
= `${title} | ${instanceName}`
|
||||
|
||||
block desc
|
||||
meta(name='description' content= clip.description)
|
||||
|
||||
block og
|
||||
meta(property='og:type' content='article')
|
||||
meta(property='og:title' content= title)
|
||||
meta(property='og:description' content= clip.description)
|
||||
meta(property='og:url' content= url)
|
||||
meta(property='og:image' content= user.avatarUrl)
|
||||
|
||||
block meta
|
||||
meta(name='misskey:user-username' content=user.username)
|
||||
meta(name='misskey:user-id' content=user.id)
|
||||
meta(name='misskey:clip-id' content=clip.id)
|
||||
|
||||
meta(name='twitter:card' content='summary')
|
||||
|
||||
// todo
|
||||
if user.twitter
|
||||
meta(name='twitter:creator' content=`@${user.twitter.screenName}`)
|
Reference in New Issue
Block a user