fix(backend): add detailed schema to `fetch-rss` endpoint (#13764)

This commit is contained in:
zyoshoka 2024-04-29 15:36:01 +09:00 committed by GitHub
parent e2ff5f58b2
commit 2ff90a80d4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 234 additions and 11 deletions

View File

@ -20,13 +20,188 @@ export const meta = {
res: { res: {
type: 'object', type: 'object',
properties: { properties: {
image: {
type: 'object',
optional: true,
properties: {
link: {
type: 'string',
optional: true,
},
url: {
type: 'string',
optional: false,
},
title: {
type: 'string',
optional: true,
},
},
},
paginationLinks: {
type: 'object',
optional: true,
properties: {
self: {
type: 'string',
optional: true,
},
first: {
type: 'string',
optional: true,
},
next: {
type: 'string',
optional: true,
},
last: {
type: 'string',
optional: true,
},
prev: {
type: 'string',
optional: true,
},
},
},
link: {
type: 'string',
optional: true,
},
title: {
type: 'string',
optional: true,
},
items: { items: {
type: 'array', type: 'array',
optional: false,
items: { items: {
type: 'object', type: 'object',
properties: {
link: {
type: 'string',
optional: true,
},
guid: {
type: 'string',
optional: true,
},
title: {
type: 'string',
optional: true,
},
pubDate: {
type: 'string',
optional: true,
},
creator: {
type: 'string',
optional: true,
},
summary: {
type: 'string',
optional: true,
},
content: {
type: 'string',
optional: true,
},
isoDate: {
type: 'string',
optional: true,
},
categories: {
type: 'array',
optional: true,
items: {
type: 'string',
},
},
contentSnippet: {
type: 'string',
optional: true,
},
enclosure: {
type: 'object',
optional: true,
properties: {
url: {
type: 'string',
optional: false,
},
length: {
type: 'number',
optional: true,
},
type: {
type: 'string',
optional: true,
},
},
},
},
}, },
} },
} feedUrl: {
type: 'string',
optional: true,
},
description: {
type: 'string',
optional: true,
},
itunes: {
type: 'object',
optional: true,
additionalProperties: true,
properties: {
image: {
type: 'string',
optional: true,
},
owner: {
type: 'object',
optional: true,
properties: {
name: {
type: 'string',
optional: true,
},
email: {
type: 'string',
optional: true,
},
},
},
author: {
type: 'string',
optional: true,
},
summary: {
type: 'string',
optional: true,
},
explicit: {
type: 'string',
optional: true,
},
categories: {
type: 'array',
optional: true,
items: {
type: 'string',
},
},
keywords: {
type: 'array',
optional: true,
items: {
type: 'string',
},
},
},
},
},
}, },
} as const; } as const;

View File

@ -28,6 +28,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup> <script lang="ts" setup>
import { ref } from 'vue'; import { ref } from 'vue';
import * as Misskey from 'misskey-js';
import MarqueeText from '@/components/MkMarquee.vue'; import MarqueeText from '@/components/MkMarquee.vue';
import { useInterval } from '@/scripts/use-interval.js'; import { useInterval } from '@/scripts/use-interval.js';
import { shuffle } from '@/scripts/shuffle.js'; import { shuffle } from '@/scripts/shuffle.js';
@ -42,13 +43,13 @@ const props = defineProps<{
refreshIntervalSec?: number; refreshIntervalSec?: number;
}>(); }>();
const items = ref([]); const items = ref<Misskey.entities.FetchRssResponse['items']>([]);
const fetching = ref(true); const fetching = ref(true);
const key = ref(0); const key = ref(0);
const tick = () => { const tick = () => {
window.fetch(`/api/fetch-rss?url=${props.url}`, {}).then(res => { window.fetch(`/api/fetch-rss?url=${props.url}`, {}).then(res => {
res.json().then(feed => { res.json().then((feed: Misskey.entities.FetchRssResponse) => {
if (props.shuffle) { if (props.shuffle) {
shuffle(feed.items); shuffle(feed.items);
} }

View File

@ -24,6 +24,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup> <script lang="ts" setup>
import { ref, watch, computed } from 'vue'; import { ref, watch, computed } from 'vue';
import * as Misskey from 'misskey-js';
import { useWidgetPropsManager, WidgetComponentEmits, WidgetComponentExpose, WidgetComponentProps } from './widget.js'; import { useWidgetPropsManager, WidgetComponentEmits, WidgetComponentExpose, WidgetComponentProps } from './widget.js';
import { GetFormResultType } from '@/scripts/form.js'; import { GetFormResultType } from '@/scripts/form.js';
import MkContainer from '@/components/MkContainer.vue'; import MkContainer from '@/components/MkContainer.vue';
@ -64,7 +65,7 @@ const { widgetProps, configure } = useWidgetPropsManager(name,
emit, emit,
); );
const rawItems = ref([]); const rawItems = ref<Misskey.entities.FetchRssResponse['items']>([]);
const items = computed(() => rawItems.value.slice(0, widgetProps.maxEntries)); const items = computed(() => rawItems.value.slice(0, widgetProps.maxEntries));
const fetching = ref(true); const fetching = ref(true);
const fetchEndpoint = computed(() => { const fetchEndpoint = computed(() => {
@ -79,8 +80,8 @@ const tick = () => {
window.fetch(fetchEndpoint.value, {}) window.fetch(fetchEndpoint.value, {})
.then(res => res.json()) .then(res => res.json())
.then(feed => { .then((feed: Misskey.entities.FetchRssResponse) => {
rawItems.value = feed.items ?? []; rawItems.value = feed.items;
fetching.value = false; fetching.value = false;
}); });
}; };

View File

@ -28,6 +28,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup> <script lang="ts" setup>
import { ref, watch, computed } from 'vue'; import { ref, watch, computed } from 'vue';
import * as Misskey from 'misskey-js';
import { useWidgetPropsManager, WidgetComponentEmits, WidgetComponentExpose, WidgetComponentProps } from './widget.js'; import { useWidgetPropsManager, WidgetComponentEmits, WidgetComponentExpose, WidgetComponentProps } from './widget.js';
import MarqueeText from '@/components/MkMarquee.vue'; import MarqueeText from '@/components/MkMarquee.vue';
import { GetFormResultType } from '@/scripts/form.js'; import { GetFormResultType } from '@/scripts/form.js';
@ -87,7 +88,7 @@ const { widgetProps, configure } = useWidgetPropsManager(name,
emit, emit,
); );
const rawItems = ref([]); const rawItems = ref<Misskey.entities.FetchRssResponse['items']>([]);
const items = computed(() => { const items = computed(() => {
const newItems = rawItems.value.slice(0, widgetProps.maxEntries); const newItems = rawItems.value.slice(0, widgetProps.maxEntries);
if (widgetProps.shuffle) { if (widgetProps.shuffle) {
@ -110,8 +111,8 @@ const tick = () => {
window.fetch(fetchEndpoint.value, {}) window.fetch(fetchEndpoint.value, {})
.then(res => res.json()) .then(res => res.json())
.then(feed => { .then((feed: Misskey.entities.FetchRssResponse) => {
rawItems.value = feed.items ?? []; rawItems.value = feed.items;
fetching.value = false; fetching.value = false;
key.value++; key.value++;
}); });

View File

@ -26065,7 +26065,52 @@ export type operations = {
200: { 200: {
content: { content: {
'application/json': { 'application/json': {
items: Record<string, never>[]; image?: {
link?: string;
url: string;
title?: string;
};
paginationLinks?: {
self?: string;
first?: string;
next?: string;
last?: string;
prev?: string;
};
link?: string;
title?: string;
items: {
link?: string;
guid?: string;
title?: string;
pubDate?: string;
creator?: string;
summary?: string;
content?: string;
isoDate?: string;
categories?: string[];
contentSnippet?: string;
enclosure?: {
url: string;
length?: number;
type?: string;
};
}[];
feedUrl?: string;
description?: string;
itunes?: {
image?: string;
owner?: {
name?: string;
email?: string;
};
author?: string;
summary?: string;
explicit?: string;
categories?: string[];
keywords?: string[];
[key: string]: unknown;
};
}; };
}; };
}; };