Removed calckey-js and removed channels
This commit is contained in:
parent
b58917aabb
commit
b04076fbf0
|
@ -8,7 +8,6 @@ RUN apk add --no-cache --no-progress git alpine-sdk python3 nodejs-current npm v
|
||||||
# Copy only the dependency-related files first, to cache efficiently
|
# Copy only the dependency-related files first, to cache efficiently
|
||||||
COPY package.json pnpm*.yaml ./
|
COPY package.json pnpm*.yaml ./
|
||||||
COPY packages/backend/package.json packages/backend/package.json
|
COPY packages/backend/package.json packages/backend/package.json
|
||||||
COPY packages/calckey-js/package.json packages/calckey-js/package.json
|
|
||||||
|
|
||||||
# Configure corepack and pnpm, and install dev mode dependencies for compilation
|
# Configure corepack and pnpm, and install dev mode dependencies for compilation
|
||||||
RUN corepack enable && corepack prepare pnpm@latest --activate && pnpm i --frozen-lockfile
|
RUN corepack enable && corepack prepare pnpm@latest --activate && pnpm i --frozen-lockfile
|
||||||
|
@ -32,7 +31,6 @@ COPY . ./
|
||||||
# Copy node modules
|
# Copy node modules
|
||||||
COPY --from=build /calckey/node_modules /calckey/node_modules
|
COPY --from=build /calckey/node_modules /calckey/node_modules
|
||||||
COPY --from=build /calckey/packages/backend/node_modules /calckey/packages/backend/node_modules
|
COPY --from=build /calckey/packages/backend/node_modules /calckey/packages/backend/node_modules
|
||||||
COPY --from=build /calckey/packages/calckey-js/node_modules /calckey/packages/calckey-js/node_modules
|
|
||||||
|
|
||||||
# Copy the finished compiled files
|
# Copy the finished compiled files
|
||||||
COPY --from=build /calckey/packages/backend/built /calckey/packages/backend/built
|
COPY --from=build /calckey/packages/backend/built /calckey/packages/backend/built
|
||||||
|
|
|
@ -36,7 +36,6 @@
|
||||||
"cross-env": "7.0.3",
|
"cross-env": "7.0.3",
|
||||||
"execa": "5.1.1",
|
"execa": "5.1.1",
|
||||||
"install-peers": "^1.0.4",
|
"install-peers": "^1.0.4",
|
||||||
"rome": "^12.1.3",
|
|
||||||
"start-server-and-test": "1.15.2",
|
"start-server-and-test": "1.15.2",
|
||||||
"typescript": "4.9.4"
|
"typescript": "4.9.4"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
# 📦 Packages
|
|
||||||
|
|
||||||
This directory contains all of the packages Calckey uses.
|
|
||||||
|
|
||||||
- `backend`: Main backend code written in TypeScript for NodeJS
|
|
||||||
- `backend/native-utils`: Backend code written in Rust, bound to NodeJS by [NAPI-RS](https://napi.rs/)
|
|
||||||
- `client`: Web interface written in Vue3 and TypeScript
|
|
||||||
- `sw`: Web [Service Worker](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) written in TypeScript
|
|
||||||
- `calckey-js`: TypeScript SDK for both backend and client, also published on [NPM](https://www.npmjs.com/package/calckey-js) for public use
|
|
|
@ -7,10 +7,7 @@
|
||||||
"start": "pnpm node ./built/index.js",
|
"start": "pnpm node ./built/index.js",
|
||||||
"start:test": "NODE_ENV=test pnpm node ./built/index.js",
|
"start:test": "NODE_ENV=test pnpm node ./built/index.js",
|
||||||
"build": "pnpm swc src -d built -D",
|
"build": "pnpm swc src -d built -D",
|
||||||
"watch": "pnpm swc src -d built -D -w",
|
"watch": "pnpm swc src -d built -D -w"
|
||||||
"lint": "pnpm rome check --apply *",
|
|
||||||
"test": "pnpm run mocha",
|
|
||||||
"format": "pnpm rome format * --write"
|
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@swc/core-android-arm64": "1.3.11"
|
"@swc/core-android-arm64": "1.3.11"
|
||||||
|
@ -41,7 +38,6 @@
|
||||||
"blurhash": "1.1.5",
|
"blurhash": "1.1.5",
|
||||||
"bull": "4.10.4",
|
"bull": "4.10.4",
|
||||||
"cacheable-lookup": "7.0.0",
|
"cacheable-lookup": "7.0.0",
|
||||||
"calckey-js": "workspace:*",
|
|
||||||
"cbor": "8.1.0",
|
"cbor": "8.1.0",
|
||||||
"chalk": "5.2.0",
|
"chalk": "5.2.0",
|
||||||
"chalk-template": "0.4.0",
|
"chalk-template": "0.4.0",
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { Health, Index, MeiliSearch, Stats } from "meilisearch";
|
import {Health, Index, MeiliSearch, Stats} from "meilisearch";
|
||||||
import { dbLogger } from "./logger.js";
|
import {dbLogger} from "./logger.js";
|
||||||
|
|
||||||
import config from "@/config/index.js";
|
import config from "@/config/index.js";
|
||||||
import { Note } from "@/models/entities/note.js";
|
import {Note} from "@/models/entities/note.js";
|
||||||
import * as url from "url";
|
import * as url from "url";
|
||||||
import { ILocalUser } from "@/models/entities/user.js";
|
import {ILocalUser} from "@/models/entities/user.js";
|
||||||
import { Followings, Users } from "@/models/index.js";
|
import {Followings, Users} from "@/models/index.js";
|
||||||
|
|
||||||
const logger = dbLogger.createSubLogger("meilisearch", "gray", false);
|
const logger = dbLogger.createSubLogger("meilisearch", "gray", false);
|
||||||
|
|
||||||
|
@ -130,7 +130,6 @@ export type MeilisearchNote = {
|
||||||
userId: string;
|
userId: string;
|
||||||
userHost: string;
|
userHost: string;
|
||||||
userName: string;
|
userName: string;
|
||||||
channelId: string;
|
|
||||||
mediaAttachment: string;
|
mediaAttachment: string;
|
||||||
createdAt: number;
|
createdAt: number;
|
||||||
};
|
};
|
||||||
|
@ -346,7 +345,6 @@ export default hasConfig
|
||||||
note.userHost !== ""
|
note.userHost !== ""
|
||||||
? note.userHost
|
? note.userHost
|
||||||
: url.parse(config.host).host,
|
: url.parse(config.host).host,
|
||||||
channelId: note.channelId ? note.channelId : "",
|
|
||||||
mediaAttachment: attachmentType,
|
mediaAttachment: attachmentType,
|
||||||
userName: note.user?.username ?? "UNKNOWN",
|
userName: note.user?.username ?? "UNKNOWN",
|
||||||
createdAt: note.createdAt.getTime() / 1000, // division by 1000 is necessary because Node returns in ms-accuracy
|
createdAt: note.createdAt.getTime() / 1000, // division by 1000 is necessary because Node returns in ms-accuracy
|
||||||
|
|
|
@ -60,9 +60,6 @@ import {PromoNote} from "@/models/entities/promo-note.js";
|
||||||
import {PromoRead} from "@/models/entities/promo-read.js";
|
import {PromoRead} from "@/models/entities/promo-read.js";
|
||||||
import {Relay} from "@/models/entities/relay.js";
|
import {Relay} from "@/models/entities/relay.js";
|
||||||
import {MutedNote} from "@/models/entities/muted-note.js";
|
import {MutedNote} from "@/models/entities/muted-note.js";
|
||||||
import {Channel} from "@/models/entities/channel.js";
|
|
||||||
import {ChannelFollowing} from "@/models/entities/channel-following.js";
|
|
||||||
import {ChannelNotePining} from "@/models/entities/channel-note-pining.js";
|
|
||||||
import {RegistryItem} from "@/models/entities/registry-item.js";
|
import {RegistryItem} from "@/models/entities/registry-item.js";
|
||||||
import {Ad} from "@/models/entities/ad.js";
|
import {Ad} from "@/models/entities/ad.js";
|
||||||
import {PasswordResetRequest} from "@/models/entities/password-reset-request.js";
|
import {PasswordResetRequest} from "@/models/entities/password-reset-request.js";
|
||||||
|
@ -169,9 +166,6 @@ export const entities = [
|
||||||
PromoRead,
|
PromoRead,
|
||||||
Relay,
|
Relay,
|
||||||
MutedNote,
|
MutedNote,
|
||||||
Channel,
|
|
||||||
ChannelFollowing,
|
|
||||||
ChannelNotePining,
|
|
||||||
RegistryItem,
|
RegistryItem,
|
||||||
Ad,
|
Ad,
|
||||||
PasswordResetRequest,
|
PasswordResetRequest,
|
||||||
|
|
|
@ -23,8 +23,6 @@ export const kinds = [
|
||||||
"read:page-likes",
|
"read:page-likes",
|
||||||
"read:user-groups",
|
"read:user-groups",
|
||||||
"write:user-groups",
|
"write:user-groups",
|
||||||
"read:channels",
|
|
||||||
"write:channels",
|
|
||||||
"read:gallery",
|
"read:gallery",
|
||||||
"write:gallery",
|
"write:gallery",
|
||||||
"read:gallery-likes",
|
"read:gallery-likes",
|
||||||
|
|
|
@ -1,35 +1,34 @@
|
||||||
import {
|
import {
|
||||||
packedUserLiteSchema,
|
|
||||||
packedUserDetailedNotMeOnlySchema,
|
|
||||||
packedMeDetailedOnlySchema,
|
packedMeDetailedOnlySchema,
|
||||||
packedUserDetailedNotMeSchema,
|
|
||||||
packedMeDetailedSchema,
|
packedMeDetailedSchema,
|
||||||
|
packedUserDetailedNotMeOnlySchema,
|
||||||
|
packedUserDetailedNotMeSchema,
|
||||||
packedUserDetailedSchema,
|
packedUserDetailedSchema,
|
||||||
|
packedUserLiteSchema,
|
||||||
packedUserSchema,
|
packedUserSchema,
|
||||||
} from "@/models/schema/user.js";
|
} from "@/models/schema/user.js";
|
||||||
import { packedNoteSchema } from "@/models/schema/note.js";
|
import {packedNoteSchema} from "@/models/schema/note.js";
|
||||||
import { packedUserListSchema } from "@/models/schema/user-list.js";
|
import {packedUserListSchema} from "@/models/schema/user-list.js";
|
||||||
import { packedAppSchema } from "@/models/schema/app.js";
|
import {packedAppSchema} from "@/models/schema/app.js";
|
||||||
import { packedNotificationSchema } from "@/models/schema/notification.js";
|
import {packedNotificationSchema} from "@/models/schema/notification.js";
|
||||||
import { packedDriveFileSchema } from "@/models/schema/drive-file.js";
|
import {packedDriveFileSchema} from "@/models/schema/drive-file.js";
|
||||||
import { packedDriveFolderSchema } from "@/models/schema/drive-folder.js";
|
import {packedDriveFolderSchema} from "@/models/schema/drive-folder.js";
|
||||||
import { packedFollowingSchema } from "@/models/schema/following.js";
|
import {packedFollowingSchema} from "@/models/schema/following.js";
|
||||||
import { packedMutingSchema } from "@/models/schema/muting.js";
|
import {packedMutingSchema} from "@/models/schema/muting.js";
|
||||||
import { packedRenoteMutingSchema } from "@/models/schema/renote-muting.js";
|
import {packedRenoteMutingSchema} from "@/models/schema/renote-muting.js";
|
||||||
import { packedBlockingSchema } from "@/models/schema/blocking.js";
|
import {packedBlockingSchema} from "@/models/schema/blocking.js";
|
||||||
import { packedNoteReactionSchema } from "@/models/schema/note-reaction.js";
|
import {packedNoteReactionSchema} from "@/models/schema/note-reaction.js";
|
||||||
import { packedHashtagSchema } from "@/models/schema/hashtag.js";
|
import {packedHashtagSchema} from "@/models/schema/hashtag.js";
|
||||||
import { packedPageSchema } from "@/models/schema/page.js";
|
import {packedPageSchema} from "@/models/schema/page.js";
|
||||||
import { packedUserGroupSchema } from "@/models/schema/user-group.js";
|
import {packedUserGroupSchema} from "@/models/schema/user-group.js";
|
||||||
import { packedNoteFavoriteSchema } from "@/models/schema/note-favorite.js";
|
import {packedNoteFavoriteSchema} from "@/models/schema/note-favorite.js";
|
||||||
import { packedChannelSchema } from "@/models/schema/channel.js";
|
import {packedAntennaSchema} from "@/models/schema/antenna.js";
|
||||||
import { packedAntennaSchema } from "@/models/schema/antenna.js";
|
import {packedClipSchema} from "@/models/schema/clip.js";
|
||||||
import { packedClipSchema } from "@/models/schema/clip.js";
|
import {packedFederationInstanceSchema} from "@/models/schema/federation-instance.js";
|
||||||
import { packedFederationInstanceSchema } from "@/models/schema/federation-instance.js";
|
import {packedQueueCountSchema} from "@/models/schema/queue.js";
|
||||||
import { packedQueueCountSchema } from "@/models/schema/queue.js";
|
import {packedGalleryPostSchema} from "@/models/schema/gallery-post.js";
|
||||||
import { packedGalleryPostSchema } from "@/models/schema/gallery-post.js";
|
import {packedEmojiSchema} from "@/models/schema/emoji.js";
|
||||||
import { packedEmojiSchema } from "@/models/schema/emoji.js";
|
import {packedNoteEdit} from "@/models/schema/note-edit.js";
|
||||||
import { packedNoteEdit } from "@/models/schema/note-edit.js";
|
|
||||||
|
|
||||||
export const refs = {
|
export const refs = {
|
||||||
UserLite: packedUserLiteSchema,
|
UserLite: packedUserLiteSchema,
|
||||||
|
@ -56,7 +55,6 @@ export const refs = {
|
||||||
Blocking: packedBlockingSchema,
|
Blocking: packedBlockingSchema,
|
||||||
Hashtag: packedHashtagSchema,
|
Hashtag: packedHashtagSchema,
|
||||||
Page: packedPageSchema,
|
Page: packedPageSchema,
|
||||||
Channel: packedChannelSchema,
|
|
||||||
QueueCount: packedQueueCountSchema,
|
QueueCount: packedQueueCountSchema,
|
||||||
Antenna: packedAntennaSchema,
|
Antenna: packedAntennaSchema,
|
||||||
Clip: packedClipSchema,
|
Clip: packedClipSchema,
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
import {
|
|
||||||
PrimaryColumn,
|
|
||||||
Entity,
|
|
||||||
Index,
|
|
||||||
JoinColumn,
|
|
||||||
Column,
|
|
||||||
ManyToOne,
|
|
||||||
} from "typeorm";
|
|
||||||
import { User } from "./user.js";
|
|
||||||
import { id } from "../id.js";
|
|
||||||
import { Channel } from "./channel.js";
|
|
||||||
|
|
||||||
@Entity()
|
|
||||||
@Index(["followerId", "followeeId"], { unique: true })
|
|
||||||
export class ChannelFollowing {
|
|
||||||
@PrimaryColumn(id())
|
|
||||||
public id: string;
|
|
||||||
|
|
||||||
@Index()
|
|
||||||
@Column("timestamp with time zone", {
|
|
||||||
comment: "The created date of the ChannelFollowing.",
|
|
||||||
})
|
|
||||||
public createdAt: Date;
|
|
||||||
|
|
||||||
@Index()
|
|
||||||
@Column({
|
|
||||||
...id(),
|
|
||||||
comment: "The followee channel ID.",
|
|
||||||
})
|
|
||||||
public followeeId: Channel["id"];
|
|
||||||
|
|
||||||
@ManyToOne((type) => Channel, {
|
|
||||||
onDelete: "CASCADE",
|
|
||||||
})
|
|
||||||
@JoinColumn()
|
|
||||||
public followee: Channel | null;
|
|
||||||
|
|
||||||
@Index()
|
|
||||||
@Column({
|
|
||||||
...id(),
|
|
||||||
comment: "The follower user ID.",
|
|
||||||
})
|
|
||||||
public followerId: User["id"];
|
|
||||||
|
|
||||||
@ManyToOne((type) => User, {
|
|
||||||
onDelete: "CASCADE",
|
|
||||||
})
|
|
||||||
@JoinColumn()
|
|
||||||
public follower: User | null;
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
import {
|
|
||||||
PrimaryColumn,
|
|
||||||
Entity,
|
|
||||||
Index,
|
|
||||||
JoinColumn,
|
|
||||||
Column,
|
|
||||||
ManyToOne,
|
|
||||||
} from "typeorm";
|
|
||||||
import { Note } from "./note.js";
|
|
||||||
import { Channel } from "./channel.js";
|
|
||||||
import { id } from "../id.js";
|
|
||||||
|
|
||||||
@Entity()
|
|
||||||
@Index(["channelId", "noteId"], { unique: true })
|
|
||||||
export class ChannelNotePining {
|
|
||||||
@PrimaryColumn(id())
|
|
||||||
public id: string;
|
|
||||||
|
|
||||||
@Column("timestamp with time zone", {
|
|
||||||
comment: "The created date of the ChannelNotePining.",
|
|
||||||
})
|
|
||||||
public createdAt: Date;
|
|
||||||
|
|
||||||
@Index()
|
|
||||||
@Column(id())
|
|
||||||
public channelId: Channel["id"];
|
|
||||||
|
|
||||||
@ManyToOne((type) => Channel, {
|
|
||||||
onDelete: "CASCADE",
|
|
||||||
})
|
|
||||||
@JoinColumn()
|
|
||||||
public channel: Channel | null;
|
|
||||||
|
|
||||||
@Column(id())
|
|
||||||
public noteId: Note["id"];
|
|
||||||
|
|
||||||
@ManyToOne((type) => Note, {
|
|
||||||
onDelete: "CASCADE",
|
|
||||||
})
|
|
||||||
@JoinColumn()
|
|
||||||
public note: Note | null;
|
|
||||||
}
|
|
|
@ -1,83 +0,0 @@
|
||||||
import {
|
|
||||||
PrimaryColumn,
|
|
||||||
Entity,
|
|
||||||
Index,
|
|
||||||
JoinColumn,
|
|
||||||
Column,
|
|
||||||
ManyToOne,
|
|
||||||
} from "typeorm";
|
|
||||||
import { User } from "./user.js";
|
|
||||||
import { id } from "../id.js";
|
|
||||||
import { DriveFile } from "./drive-file.js";
|
|
||||||
|
|
||||||
@Entity()
|
|
||||||
export class Channel {
|
|
||||||
@PrimaryColumn(id())
|
|
||||||
public id: string;
|
|
||||||
|
|
||||||
@Index()
|
|
||||||
@Column("timestamp with time zone", {
|
|
||||||
comment: "The created date of the Channel.",
|
|
||||||
})
|
|
||||||
public createdAt: Date;
|
|
||||||
|
|
||||||
@Index()
|
|
||||||
@Column("timestamp with time zone", {
|
|
||||||
nullable: true,
|
|
||||||
})
|
|
||||||
public lastNotedAt: Date | null;
|
|
||||||
|
|
||||||
@Index()
|
|
||||||
@Column({
|
|
||||||
...id(),
|
|
||||||
nullable: true,
|
|
||||||
comment: "The owner ID.",
|
|
||||||
})
|
|
||||||
public userId: User["id"] | null;
|
|
||||||
|
|
||||||
@ManyToOne((type) => User, {
|
|
||||||
onDelete: "SET NULL",
|
|
||||||
})
|
|
||||||
@JoinColumn()
|
|
||||||
public user: User | null;
|
|
||||||
|
|
||||||
@Column("varchar", {
|
|
||||||
length: 128,
|
|
||||||
comment: "The name of the Channel.",
|
|
||||||
})
|
|
||||||
public name: string;
|
|
||||||
|
|
||||||
@Column("varchar", {
|
|
||||||
length: 2048,
|
|
||||||
nullable: true,
|
|
||||||
comment: "The description of the Channel.",
|
|
||||||
})
|
|
||||||
public description: string | null;
|
|
||||||
|
|
||||||
@Column({
|
|
||||||
...id(),
|
|
||||||
nullable: true,
|
|
||||||
comment: "The ID of banner Channel.",
|
|
||||||
})
|
|
||||||
public bannerId: DriveFile["id"] | null;
|
|
||||||
|
|
||||||
@ManyToOne((type) => DriveFile, {
|
|
||||||
onDelete: "SET NULL",
|
|
||||||
})
|
|
||||||
@JoinColumn()
|
|
||||||
public banner: DriveFile | null;
|
|
||||||
|
|
||||||
@Index()
|
|
||||||
@Column("integer", {
|
|
||||||
default: 0,
|
|
||||||
comment: "The count of notes.",
|
|
||||||
})
|
|
||||||
public notesCount: number;
|
|
||||||
|
|
||||||
@Index()
|
|
||||||
@Column("integer", {
|
|
||||||
default: 0,
|
|
||||||
comment: "The count of users.",
|
|
||||||
})
|
|
||||||
public usersCount: number;
|
|
||||||
}
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { Entity, Column, PrimaryColumn, ManyToOne, JoinColumn } from "typeorm";
|
import {Column, Entity, JoinColumn, ManyToOne, PrimaryColumn} from "typeorm";
|
||||||
import { id } from "../id.js";
|
import {id} from "../id.js";
|
||||||
import { User } from "./user.js";
|
import {User} from "./user.js";
|
||||||
import type { Clip } from "./clip.js";
|
import type {Clip} from "./clip.js";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class Meta {
|
export class Meta {
|
||||||
|
@ -143,7 +143,7 @@ export class Meta {
|
||||||
@Column("varchar", {
|
@Column("varchar", {
|
||||||
length: 512,
|
length: 512,
|
||||||
array: true,
|
array: true,
|
||||||
default: "{/featured,/channels,/explore,/pages,/about-calckey}",
|
default: "{/featured,/explore,/pages,/about-calckey}",
|
||||||
})
|
})
|
||||||
public pinnedPages: string[];
|
public pinnedPages: string[];
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,7 @@
|
||||||
import {
|
import {Column, Entity, Index, JoinColumn, ManyToOne, PrimaryColumn,} from "typeorm";
|
||||||
PrimaryColumn,
|
import {User} from "./user.js";
|
||||||
Entity,
|
import {Note} from "./note.js";
|
||||||
Index,
|
import {id} from "../id.js";
|
||||||
JoinColumn,
|
|
||||||
Column,
|
|
||||||
ManyToOne,
|
|
||||||
} from "typeorm";
|
|
||||||
import { User } from "./user.js";
|
|
||||||
import { Note } from "./note.js";
|
|
||||||
import { id } from "../id.js";
|
|
||||||
import type { Channel } from "./channel.js";
|
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index(["userId", "noteId"], { unique: true })
|
@Index(["userId", "noteId"], { unique: true })
|
||||||
|
@ -58,13 +50,5 @@ export class NoteUnread {
|
||||||
comment: "[Denormalized]",
|
comment: "[Denormalized]",
|
||||||
})
|
})
|
||||||
public noteUserId: User["id"];
|
public noteUserId: User["id"];
|
||||||
|
|
||||||
@Index()
|
|
||||||
@Column({
|
|
||||||
...id(),
|
|
||||||
nullable: true,
|
|
||||||
comment: "[Denormalized]",
|
|
||||||
})
|
|
||||||
public noteChannelId: Channel["id"] | null;
|
|
||||||
//#endregion
|
//#endregion
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,8 @@
|
||||||
import {
|
import {Column, Entity, Index, JoinColumn, ManyToOne, PrimaryColumn,} from "typeorm";
|
||||||
Entity,
|
import {User} from "./user.js";
|
||||||
Index,
|
import type {DriveFile} from "./drive-file.js";
|
||||||
JoinColumn,
|
import {id} from "../id.js";
|
||||||
Column,
|
import {noteVisibilities} from "../../types.js";
|
||||||
PrimaryColumn,
|
|
||||||
ManyToOne,
|
|
||||||
} from "typeorm";
|
|
||||||
import { User } from "./user.js";
|
|
||||||
import type { DriveFile } from "./drive-file.js";
|
|
||||||
import { id } from "../id.js";
|
|
||||||
import { noteVisibilities } from "../../types.js";
|
|
||||||
import { Channel } from "./channel.js";
|
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index("IDX_NOTE_TAGS", { synchronize: false })
|
@Index("IDX_NOTE_TAGS", { synchronize: false })
|
||||||
|
@ -200,20 +192,6 @@ export class Note {
|
||||||
})
|
})
|
||||||
public hasPoll: boolean;
|
public hasPoll: boolean;
|
||||||
|
|
||||||
@Index()
|
|
||||||
@Column({
|
|
||||||
...id(),
|
|
||||||
nullable: true,
|
|
||||||
comment: "The ID of source channel.",
|
|
||||||
})
|
|
||||||
public channelId: Channel["id"] | null;
|
|
||||||
|
|
||||||
@ManyToOne((type) => Channel, {
|
|
||||||
onDelete: "CASCADE",
|
|
||||||
})
|
|
||||||
@JoinColumn()
|
|
||||||
public channel: Channel | null;
|
|
||||||
|
|
||||||
//#region Denormalized fields
|
//#region Denormalized fields
|
||||||
@Index()
|
@Index()
|
||||||
@Column("varchar", {
|
@Column("varchar", {
|
||||||
|
|
|
@ -1,72 +1,67 @@
|
||||||
import {} from "typeorm";
|
import {db} from "@/db/postgre.js";
|
||||||
import { db } from "@/db/postgre.js";
|
|
||||||
|
|
||||||
import { Announcement } from "./entities/announcement.js";
|
import {Announcement} from "./entities/announcement.js";
|
||||||
import { AnnouncementRead } from "./entities/announcement-read.js";
|
import {AnnouncementRead} from "./entities/announcement-read.js";
|
||||||
import { Instance } from "./entities/instance.js";
|
import {Poll} from "./entities/poll.js";
|
||||||
import { Poll } from "./entities/poll.js";
|
import {PollVote} from "./entities/poll-vote.js";
|
||||||
import { PollVote } from "./entities/poll-vote.js";
|
import {Meta} from "./entities/meta.js";
|
||||||
import { Meta } from "./entities/meta.js";
|
import {SwSubscription} from "./entities/sw-subscription.js";
|
||||||
import { SwSubscription } from "./entities/sw-subscription.js";
|
import {NoteWatching} from "./entities/note-watching.js";
|
||||||
import { NoteWatching } from "./entities/note-watching.js";
|
import {NoteThreadMuting} from "./entities/note-thread-muting.js";
|
||||||
import { NoteThreadMuting } from "./entities/note-thread-muting.js";
|
import {NoteUnread} from "./entities/note-unread.js";
|
||||||
import { NoteUnread } from "./entities/note-unread.js";
|
import {RegistrationTicket} from "./entities/registration-tickets.js";
|
||||||
import { RegistrationTicket } from "./entities/registration-tickets.js";
|
import {UserRepository} from "./repositories/user.js";
|
||||||
import { UserRepository } from "./repositories/user.js";
|
import {NoteRepository} from "./repositories/note.js";
|
||||||
import { NoteRepository } from "./repositories/note.js";
|
import {DriveFileRepository} from "./repositories/drive-file.js";
|
||||||
import { DriveFileRepository } from "./repositories/drive-file.js";
|
import {DriveFolderRepository} from "./repositories/drive-folder.js";
|
||||||
import { DriveFolderRepository } from "./repositories/drive-folder.js";
|
import {AccessToken} from "./entities/access-token.js";
|
||||||
import { AccessToken } from "./entities/access-token.js";
|
import {UserNotePining} from "./entities/user-note-pining.js";
|
||||||
import { UserNotePining } from "./entities/user-note-pining.js";
|
import {SigninRepository} from "./repositories/signin.js";
|
||||||
import { SigninRepository } from "./repositories/signin.js";
|
import {UserListRepository} from "./repositories/user-list.js";
|
||||||
import { UserListRepository } from "./repositories/user-list.js";
|
import {UserListJoining} from "./entities/user-list-joining.js";
|
||||||
import { UserListJoining } from "./entities/user-list-joining.js";
|
import {UserGroupRepository} from "./repositories/user-group.js";
|
||||||
import { UserGroupRepository } from "./repositories/user-group.js";
|
import {UserGroupJoining} from "./entities/user-group-joining.js";
|
||||||
import { UserGroupJoining } from "./entities/user-group-joining.js";
|
import {UserGroupInvitationRepository} from "./repositories/user-group-invitation.js";
|
||||||
import { UserGroupInvitationRepository } from "./repositories/user-group-invitation.js";
|
import {FollowRequestRepository} from "./repositories/follow-request.js";
|
||||||
import { FollowRequestRepository } from "./repositories/follow-request.js";
|
import {MutingRepository} from "./repositories/muting.js";
|
||||||
import { MutingRepository } from "./repositories/muting.js";
|
import {RenoteMutingRepository} from "./repositories/renote-muting.js";
|
||||||
import { RenoteMutingRepository } from "./repositories/renote-muting.js";
|
import {BlockingRepository} from "./repositories/blocking.js";
|
||||||
import { BlockingRepository } from "./repositories/blocking.js";
|
import {NoteReactionRepository} from "./repositories/note-reaction.js";
|
||||||
import { NoteReactionRepository } from "./repositories/note-reaction.js";
|
import {NotificationRepository} from "./repositories/notification.js";
|
||||||
import { NotificationRepository } from "./repositories/notification.js";
|
import {NoteFavoriteRepository} from "./repositories/note-favorite.js";
|
||||||
import { NoteFavoriteRepository } from "./repositories/note-favorite.js";
|
import {UserPublickey} from "./entities/user-publickey.js";
|
||||||
import { UserPublickey } from "./entities/user-publickey.js";
|
import {UserKeypair} from "./entities/user-keypair.js";
|
||||||
import { UserKeypair } from "./entities/user-keypair.js";
|
import {AppRepository} from "./repositories/app.js";
|
||||||
import { AppRepository } from "./repositories/app.js";
|
import {FollowingRepository} from "./repositories/following.js";
|
||||||
import { FollowingRepository } from "./repositories/following.js";
|
import {AbuseUserReportRepository} from "./repositories/abuse-user-report.js";
|
||||||
import { AbuseUserReportRepository } from "./repositories/abuse-user-report.js";
|
import {AuthSessionRepository} from "./repositories/auth-session.js";
|
||||||
import { AuthSessionRepository } from "./repositories/auth-session.js";
|
import {UserProfile} from "./entities/user-profile.js";
|
||||||
import { UserProfile } from "./entities/user-profile.js";
|
import {AttestationChallenge} from "./entities/attestation-challenge.js";
|
||||||
import { AttestationChallenge } from "./entities/attestation-challenge.js";
|
import {UserSecurityKey} from "./entities/user-security-key.js";
|
||||||
import { UserSecurityKey } from "./entities/user-security-key.js";
|
import {HashtagRepository} from "./repositories/hashtag.js";
|
||||||
import { HashtagRepository } from "./repositories/hashtag.js";
|
import {PageRepository} from "./repositories/page.js";
|
||||||
import { PageRepository } from "./repositories/page.js";
|
import {PageLikeRepository} from "./repositories/page-like.js";
|
||||||
import { PageLikeRepository } from "./repositories/page-like.js";
|
import {GalleryPostRepository} from "./repositories/gallery-post.js";
|
||||||
import { GalleryPostRepository } from "./repositories/gallery-post.js";
|
import {GalleryLikeRepository} from "./repositories/gallery-like.js";
|
||||||
import { GalleryLikeRepository } from "./repositories/gallery-like.js";
|
import {ModerationLogRepository} from "./repositories/moderation-logs.js";
|
||||||
import { ModerationLogRepository } from "./repositories/moderation-logs.js";
|
import {UsedUsername} from "./entities/used-username.js";
|
||||||
import { UsedUsername } from "./entities/used-username.js";
|
import {ClipRepository} from "./repositories/clip.js";
|
||||||
import { ClipRepository } from "./repositories/clip.js";
|
import {ClipNote} from "./entities/clip-note.js";
|
||||||
import { ClipNote } from "./entities/clip-note.js";
|
import {AntennaRepository} from "./repositories/antenna.js";
|
||||||
import { AntennaRepository } from "./repositories/antenna.js";
|
import {AntennaNote} from "./entities/antenna-note.js";
|
||||||
import { AntennaNote } from "./entities/antenna-note.js";
|
import {PromoNote} from "./entities/promo-note.js";
|
||||||
import { PromoNote } from "./entities/promo-note.js";
|
import {PromoRead} from "./entities/promo-read.js";
|
||||||
import { PromoRead } from "./entities/promo-read.js";
|
import {EmojiRepository} from "./repositories/emoji.js";
|
||||||
import { EmojiRepository } from "./repositories/emoji.js";
|
import {RelayRepository} from "./repositories/relay.js";
|
||||||
import { RelayRepository } from "./repositories/relay.js";
|
import {MutedNote} from "./entities/muted-note.js";
|
||||||
import { ChannelRepository } from "./repositories/channel.js";
|
import {RegistryItem} from "./entities/registry-item.js";
|
||||||
import { MutedNote } from "./entities/muted-note.js";
|
import {Ad} from "./entities/ad.js";
|
||||||
import { ChannelFollowing } from "./entities/channel-following.js";
|
import {PasswordResetRequest} from "./entities/password-reset-request.js";
|
||||||
import { ChannelNotePining } from "./entities/channel-note-pining.js";
|
import {UserPending} from "./entities/user-pending.js";
|
||||||
import { RegistryItem } from "./entities/registry-item.js";
|
import {InstanceRepository} from "./repositories/instance.js";
|
||||||
import { Ad } from "./entities/ad.js";
|
import {Webhook} from "./entities/webhook.js";
|
||||||
import { PasswordResetRequest } from "./entities/password-reset-request.js";
|
import {UserIp} from "./entities/user-ip.js";
|
||||||
import { UserPending } from "./entities/user-pending.js";
|
import {NoteEdit} from "./entities/note-edit.js";
|
||||||
import { InstanceRepository } from "./repositories/instance.js";
|
|
||||||
import { Webhook } from "./entities/webhook.js";
|
|
||||||
import { UserIp } from "./entities/user-ip.js";
|
|
||||||
import { NoteEdit } from "./entities/note-edit.js";
|
|
||||||
|
|
||||||
export const Announcements = db.getRepository(Announcement);
|
export const Announcements = db.getRepository(Announcement);
|
||||||
export const AnnouncementReads = db.getRepository(AnnouncementRead);
|
export const AnnouncementReads = db.getRepository(AnnouncementRead);
|
||||||
|
@ -126,9 +121,6 @@ export const PromoNotes = db.getRepository(PromoNote);
|
||||||
export const PromoReads = db.getRepository(PromoRead);
|
export const PromoReads = db.getRepository(PromoRead);
|
||||||
export const Relays = RelayRepository;
|
export const Relays = RelayRepository;
|
||||||
export const MutedNotes = db.getRepository(MutedNote);
|
export const MutedNotes = db.getRepository(MutedNote);
|
||||||
export const Channels = ChannelRepository;
|
|
||||||
export const ChannelFollowings = db.getRepository(ChannelFollowing);
|
|
||||||
export const ChannelNotePinings = db.getRepository(ChannelNotePining);
|
|
||||||
export const RegistryItems = db.getRepository(RegistryItem);
|
export const RegistryItems = db.getRepository(RegistryItem);
|
||||||
export const Webhooks = db.getRepository(Webhook);
|
export const Webhooks = db.getRepository(Webhook);
|
||||||
export const Ads = db.getRepository(Ad);
|
export const Ads = db.getRepository(Ad);
|
||||||
|
|
|
@ -1,55 +0,0 @@
|
||||||
import { db } from "@/db/postgre.js";
|
|
||||||
import { Channel } from "@/models/entities/channel.js";
|
|
||||||
import type { Packed } from "@/misc/schema.js";
|
|
||||||
import { DriveFiles, ChannelFollowings, NoteUnreads } from "../index.js";
|
|
||||||
import type { User } from "@/models/entities/user.js";
|
|
||||||
|
|
||||||
export const ChannelRepository = db.getRepository(Channel).extend({
|
|
||||||
async pack(
|
|
||||||
src: Channel["id"] | Channel,
|
|
||||||
me?: { id: User["id"] } | null | undefined,
|
|
||||||
): Promise<Packed<"Channel">> {
|
|
||||||
const channel =
|
|
||||||
typeof src === "object" ? src : await this.findOneByOrFail({ id: src });
|
|
||||||
const meId = me ? me.id : null;
|
|
||||||
|
|
||||||
const banner = channel.bannerId
|
|
||||||
? await DriveFiles.findOneBy({ id: channel.bannerId })
|
|
||||||
: null;
|
|
||||||
|
|
||||||
const hasUnreadNote = meId
|
|
||||||
? (await NoteUnreads.findOneBy({
|
|
||||||
noteChannelId: channel.id,
|
|
||||||
userId: meId,
|
|
||||||
})) != null
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
const following = meId
|
|
||||||
? await ChannelFollowings.findOneBy({
|
|
||||||
followerId: meId,
|
|
||||||
followeeId: channel.id,
|
|
||||||
})
|
|
||||||
: null;
|
|
||||||
|
|
||||||
return {
|
|
||||||
id: channel.id,
|
|
||||||
createdAt: channel.createdAt.toISOString(),
|
|
||||||
lastNotedAt: channel.lastNotedAt
|
|
||||||
? channel.lastNotedAt.toISOString()
|
|
||||||
: null,
|
|
||||||
name: channel.name,
|
|
||||||
description: channel.description,
|
|
||||||
userId: channel.userId,
|
|
||||||
bannerUrl: banner ? DriveFiles.getPublicUrl(banner, false) : null,
|
|
||||||
usersCount: channel.usersCount,
|
|
||||||
notesCount: channel.notesCount,
|
|
||||||
|
|
||||||
...(me
|
|
||||||
? {
|
|
||||||
isFollowing: following != null,
|
|
||||||
hasUnreadNote,
|
|
||||||
}
|
|
||||||
: {}),
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -1,32 +1,16 @@
|
||||||
import { In } from "typeorm";
|
import {In} from "typeorm";
|
||||||
import * as mfm from "mfm-js";
|
import * as mfm from "mfm-js";
|
||||||
import { Note } from "@/models/entities/note.js";
|
import {Note} from "@/models/entities/note.js";
|
||||||
import type { User } from "@/models/entities/user.js";
|
import type {User} from "@/models/entities/user.js";
|
||||||
import {
|
import {DriveFiles, Followings, NoteReactions, Polls, PollVotes, Users,} from "../index.js";
|
||||||
Users,
|
import type {Packed} from "@/misc/schema.js";
|
||||||
PollVotes,
|
import {nyaize} from "@/misc/nyaize.js";
|
||||||
DriveFiles,
|
import {awaitAll} from "@/prelude/await-all.js";
|
||||||
NoteReactions,
|
import {convertLegacyReaction, convertLegacyReactions, decodeReaction,} from "@/misc/reaction-lib.js";
|
||||||
Followings,
|
import type {NoteReaction} from "@/models/entities/note-reaction.js";
|
||||||
Polls,
|
import {aggregateNoteEmojis, populateEmojis, prefetchEmojis,} from "@/misc/populate-emojis.js";
|
||||||
Channels,
|
import {db} from "@/db/postgre.js";
|
||||||
} from "../index.js";
|
import {IdentifiableError} from "@/misc/identifiable-error.js";
|
||||||
import type { Packed } from "@/misc/schema.js";
|
|
||||||
import { nyaize } from "@/misc/nyaize.js";
|
|
||||||
import { awaitAll } from "@/prelude/await-all.js";
|
|
||||||
import {
|
|
||||||
convertLegacyReaction,
|
|
||||||
convertLegacyReactions,
|
|
||||||
decodeReaction,
|
|
||||||
} from "@/misc/reaction-lib.js";
|
|
||||||
import type { NoteReaction } from "@/models/entities/note-reaction.js";
|
|
||||||
import {
|
|
||||||
aggregateNoteEmojis,
|
|
||||||
populateEmojis,
|
|
||||||
prefetchEmojis,
|
|
||||||
} from "@/misc/populate-emojis.js";
|
|
||||||
import { db } from "@/db/postgre.js";
|
|
||||||
import { IdentifiableError } from "@/misc/identifiable-error.js";
|
|
||||||
|
|
||||||
export async function populatePoll(note: Note, meId: User["id"] | null) {
|
export async function populatePoll(note: Note, meId: User["id"] | null) {
|
||||||
const poll = await Polls.findOneByOrFail({ noteId: note.id });
|
const poll = await Polls.findOneByOrFail({ noteId: note.id });
|
||||||
|
@ -186,12 +170,6 @@ export const NoteRepository = db.getRepository(Note).extend({
|
||||||
}`;
|
}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const channel = note.channelId
|
|
||||||
? note.channel
|
|
||||||
? note.channel
|
|
||||||
: await Channels.findOneBy({ id: note.channelId })
|
|
||||||
: null;
|
|
||||||
|
|
||||||
const reactionEmojiNames = Object.keys(note.reactions)
|
const reactionEmojiNames = Object.keys(note.reactions)
|
||||||
.filter((x) => x?.startsWith(":"))
|
.filter((x) => x?.startsWith(":"))
|
||||||
.map((x) => decodeReaction(x).reaction)
|
.map((x) => decodeReaction(x).reaction)
|
||||||
|
@ -225,13 +203,6 @@ export const NoteRepository = db.getRepository(Note).extend({
|
||||||
files: DriveFiles.packMany(note.fileIds),
|
files: DriveFiles.packMany(note.fileIds),
|
||||||
replyId: note.replyId,
|
replyId: note.replyId,
|
||||||
renoteId: note.renoteId,
|
renoteId: note.renoteId,
|
||||||
channelId: note.channelId || undefined,
|
|
||||||
channel: channel
|
|
||||||
? {
|
|
||||||
id: channel.id,
|
|
||||||
name: channel.name,
|
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
mentions: note.mentions.length > 0 ? note.mentions : undefined,
|
mentions: note.mentions.length > 0 ? note.mentions : undefined,
|
||||||
uri: note.uri || undefined,
|
uri: note.uri || undefined,
|
||||||
url: note.url || undefined,
|
url: note.url || undefined,
|
||||||
|
|
|
@ -1,43 +1,40 @@
|
||||||
import { URL } from "url";
|
import {In, Not} from "typeorm";
|
||||||
import { In, Not } from "typeorm";
|
|
||||||
import Ajv from "ajv";
|
import Ajv from "ajv";
|
||||||
import type { ILocalUser, IRemoteUser } from "@/models/entities/user.js";
|
import type {ILocalUser, IRemoteUser} from "@/models/entities/user.js";
|
||||||
import { User } from "@/models/entities/user.js";
|
import {User} from "@/models/entities/user.js";
|
||||||
import config from "@/config/index.js";
|
import config from "@/config/index.js";
|
||||||
import type { Packed } from "@/misc/schema.js";
|
import type {Packed} from "@/misc/schema.js";
|
||||||
import type { Promiseable } from "@/prelude/await-all.js";
|
import type {Promiseable} from "@/prelude/await-all.js";
|
||||||
import { awaitAll } from "@/prelude/await-all.js";
|
import {awaitAll} from "@/prelude/await-all.js";
|
||||||
import { populateEmojis } from "@/misc/populate-emojis.js";
|
import {populateEmojis} from "@/misc/populate-emojis.js";
|
||||||
import { getAntennas } from "@/misc/antenna-cache.js";
|
import {getAntennas} from "@/misc/antenna-cache.js";
|
||||||
import { USER_ACTIVE_THRESHOLD, USER_ONLINE_THRESHOLD } from "@/const.js";
|
import {USER_ACTIVE_THRESHOLD, USER_ONLINE_THRESHOLD} from "@/const.js";
|
||||||
import { Cache } from "@/misc/cache.js";
|
import {Cache} from "@/misc/cache.js";
|
||||||
import { db } from "@/db/postgre.js";
|
import {db} from "@/db/postgre.js";
|
||||||
import { isActor, getApId } from "@/remote/activitypub/type.js";
|
import {getApId, isActor} from "@/remote/activitypub/type.js";
|
||||||
import DbResolver from "@/remote/activitypub/db-resolver.js";
|
import DbResolver from "@/remote/activitypub/db-resolver.js";
|
||||||
import Resolver from "@/remote/activitypub/resolver.js";
|
import Resolver from "@/remote/activitypub/resolver.js";
|
||||||
import { createPerson } from "@/remote/activitypub/models/person.js";
|
import {createPerson} from "@/remote/activitypub/models/person.js";
|
||||||
import {
|
import {
|
||||||
AnnouncementReads,
|
AnnouncementReads,
|
||||||
Announcements,
|
Announcements,
|
||||||
AntennaNotes,
|
AntennaNotes,
|
||||||
Blockings,
|
Blockings,
|
||||||
ChannelFollowings,
|
|
||||||
DriveFiles,
|
DriveFiles,
|
||||||
Followings,
|
Followings,
|
||||||
FollowRequests,
|
FollowRequests,
|
||||||
Instances,
|
Instances,
|
||||||
Mutings,
|
Mutings,
|
||||||
RenoteMutings,
|
|
||||||
Notes,
|
Notes,
|
||||||
NoteUnreads,
|
NoteUnreads,
|
||||||
Notifications,
|
Notifications,
|
||||||
Pages,
|
Pages,
|
||||||
UserGroupJoinings,
|
RenoteMutings,
|
||||||
UserNotePinings,
|
UserNotePinings,
|
||||||
UserProfiles,
|
UserProfiles,
|
||||||
UserSecurityKeys,
|
UserSecurityKeys,
|
||||||
} from "../index.js";
|
} from "../index.js";
|
||||||
import type { Instance } from "../entities/instance.js";
|
import type {Instance} from "../entities/instance.js";
|
||||||
|
|
||||||
const userInstanceCache = new Cache<Instance | null>(1000 * 60 * 60 * 3);
|
const userInstanceCache = new Cache<Instance | null>(1000 * 60 * 60 * 3);
|
||||||
|
|
||||||
|
@ -238,20 +235,6 @@ export const UserRepository = db.getRepository(User).extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
async getHasUnreadChannel(userId: User["id"]): Promise<boolean> {
|
|
||||||
const channels = await ChannelFollowings.findBy({ followerId: userId });
|
|
||||||
|
|
||||||
const unread =
|
|
||||||
channels.length > 0
|
|
||||||
? await NoteUnreads.findOneBy({
|
|
||||||
userId: userId,
|
|
||||||
noteChannelId: In(channels.map((x) => x.followeeId)),
|
|
||||||
})
|
|
||||||
: null;
|
|
||||||
|
|
||||||
return unread != null;
|
|
||||||
},
|
|
||||||
|
|
||||||
async getHasUnreadNotification(userId: User["id"]): Promise<boolean> {
|
async getHasUnreadNotification(userId: User["id"]): Promise<boolean> {
|
||||||
const mute = await Mutings.findBy({
|
const mute = await Mutings.findBy({
|
||||||
muterId: userId,
|
muterId: userId,
|
||||||
|
@ -518,7 +501,6 @@ export const UserRepository = db.getRepository(User).extend({
|
||||||
}).then((count) => count > 0),
|
}).then((count) => count > 0),
|
||||||
hasUnreadAnnouncement: this.getHasUnreadAnnouncement(user.id),
|
hasUnreadAnnouncement: this.getHasUnreadAnnouncement(user.id),
|
||||||
hasUnreadAntenna: this.getHasUnreadAntenna(user.id),
|
hasUnreadAntenna: this.getHasUnreadAntenna(user.id),
|
||||||
hasUnreadChannel: this.getHasUnreadChannel(user.id),
|
|
||||||
hasUnreadNotification: this.getHasUnreadNotification(user.id),
|
hasUnreadNotification: this.getHasUnreadNotification(user.id),
|
||||||
hasPendingReceivedFollowRequest:
|
hasPendingReceivedFollowRequest:
|
||||||
this.getHasPendingReceivedFollowRequest(user.id),
|
this.getHasPendingReceivedFollowRequest(user.id),
|
||||||
|
|
|
@ -1,61 +0,0 @@
|
||||||
export const packedChannelSchema = {
|
|
||||||
type: "object",
|
|
||||||
properties: {
|
|
||||||
id: {
|
|
||||||
type: "string",
|
|
||||||
optional: false,
|
|
||||||
nullable: false,
|
|
||||||
format: "id",
|
|
||||||
example: "xxxxxxxxxx",
|
|
||||||
},
|
|
||||||
createdAt: {
|
|
||||||
type: "string",
|
|
||||||
optional: false,
|
|
||||||
nullable: false,
|
|
||||||
format: "date-time",
|
|
||||||
},
|
|
||||||
lastNotedAt: {
|
|
||||||
type: "string",
|
|
||||||
optional: false,
|
|
||||||
nullable: true,
|
|
||||||
format: "date-time",
|
|
||||||
},
|
|
||||||
name: {
|
|
||||||
type: "string",
|
|
||||||
optional: false,
|
|
||||||
nullable: false,
|
|
||||||
},
|
|
||||||
description: {
|
|
||||||
type: "string",
|
|
||||||
nullable: true,
|
|
||||||
optional: false,
|
|
||||||
},
|
|
||||||
bannerUrl: {
|
|
||||||
type: "string",
|
|
||||||
format: "url",
|
|
||||||
nullable: true,
|
|
||||||
optional: false,
|
|
||||||
},
|
|
||||||
notesCount: {
|
|
||||||
type: "number",
|
|
||||||
nullable: false,
|
|
||||||
optional: false,
|
|
||||||
},
|
|
||||||
usersCount: {
|
|
||||||
type: "number",
|
|
||||||
nullable: false,
|
|
||||||
optional: false,
|
|
||||||
},
|
|
||||||
isFollowing: {
|
|
||||||
type: "boolean",
|
|
||||||
optional: true,
|
|
||||||
nullable: false,
|
|
||||||
},
|
|
||||||
userId: {
|
|
||||||
type: "string",
|
|
||||||
nullable: true,
|
|
||||||
optional: false,
|
|
||||||
format: "id",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} as const;
|
|
|
@ -126,35 +126,6 @@ export const packedNoteSchema = {
|
||||||
optional: true,
|
optional: true,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
},
|
},
|
||||||
channelId: {
|
|
||||||
type: "string",
|
|
||||||
optional: true,
|
|
||||||
nullable: true,
|
|
||||||
format: "id",
|
|
||||||
example: "xxxxxxxxxx",
|
|
||||||
},
|
|
||||||
channel: {
|
|
||||||
type: "object",
|
|
||||||
optional: true,
|
|
||||||
nullable: true,
|
|
||||||
items: {
|
|
||||||
type: "object",
|
|
||||||
optional: false,
|
|
||||||
nullable: false,
|
|
||||||
properties: {
|
|
||||||
id: {
|
|
||||||
type: "string",
|
|
||||||
optional: false,
|
|
||||||
nullable: false,
|
|
||||||
},
|
|
||||||
name: {
|
|
||||||
type: "string",
|
|
||||||
optional: false,
|
|
||||||
nullable: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
localOnly: {
|
localOnly: {
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
optional: true,
|
optional: true,
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import create from "@/services/note/create.js";
|
import create from "@/services/note/create.js";
|
||||||
import { Users } from "@/models/index.js";
|
import {Users} from "@/models/index.js";
|
||||||
import type { DbUserImportMastoPostJobData } from "@/queue/types.js";
|
import type {DbUserImportMastoPostJobData} from "@/queue/types.js";
|
||||||
import { queueLogger } from "../../logger.js";
|
import {queueLogger} from "../../logger.js";
|
||||||
import type Bull from "bull";
|
import type Bull from "bull";
|
||||||
import { htmlToMfm } from "@/remote/activitypub/misc/html-to-mfm.js";
|
import {htmlToMfm} from "@/remote/activitypub/misc/html-to-mfm.js";
|
||||||
import { resolveNote } from "@/remote/activitypub/models/note.js";
|
import {resolveNote} from "@/remote/activitypub/models/note.js";
|
||||||
import { Note } from "@/models/entities/note.js";
|
import {Note} from "@/models/entities/note.js";
|
||||||
|
|
||||||
const logger = queueLogger.createSubLogger("import-masto-post");
|
const logger = queueLogger.createSubLogger("import-masto-post");
|
||||||
|
|
||||||
|
@ -54,7 +54,6 @@ export async function importMastoPost(
|
||||||
localOnly: false,
|
localOnly: false,
|
||||||
visibility: "hidden",
|
visibility: "hidden",
|
||||||
visibleUsers: [],
|
visibleUsers: [],
|
||||||
channel: null,
|
|
||||||
apMentions: new Array(0),
|
apMentions: new Array(0),
|
||||||
apHashtags: undefined,
|
apHashtags: undefined,
|
||||||
apEmojis: undefined,
|
apEmojis: undefined,
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
import type { User } from "@/models/entities/user.js";
|
|
||||||
import { ChannelFollowings } from "@/models/index.js";
|
|
||||||
import type { SelectQueryBuilder } from "typeorm";
|
|
||||||
import { Brackets } from "typeorm";
|
|
||||||
|
|
||||||
export function generateChannelQuery(
|
|
||||||
q: SelectQueryBuilder<any>,
|
|
||||||
me?: { id: User["id"] } | null,
|
|
||||||
) {
|
|
||||||
if (me == null) {
|
|
||||||
q.andWhere("note.channelId IS NULL");
|
|
||||||
} else {
|
|
||||||
q.leftJoinAndSelect("note.channel", "channel");
|
|
||||||
|
|
||||||
const channelFollowingQuery = ChannelFollowings.createQueryBuilder(
|
|
||||||
"channelFollowing",
|
|
||||||
)
|
|
||||||
.select("channelFollowing.followeeId")
|
|
||||||
.where("channelFollowing.followerId = :followerId", {
|
|
||||||
followerId: me.id,
|
|
||||||
});
|
|
||||||
|
|
||||||
q.andWhere(
|
|
||||||
new Brackets((qb) => {
|
|
||||||
qb
|
|
||||||
// チャンネルのノートではない
|
|
||||||
.where("note.channelId IS NULL")
|
|
||||||
// または自分がフォローしているチャンネルのノート
|
|
||||||
.orWhere(`note.channelId IN (${channelFollowingQuery.getQuery()})`);
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
q.setParameters(channelFollowingQuery.getParameters());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -86,16 +86,6 @@ import * as ep___auth_session_userkey from "./endpoints/auth/session/userkey.js"
|
||||||
import * as ep___blocking_create from "./endpoints/blocking/create.js";
|
import * as ep___blocking_create from "./endpoints/blocking/create.js";
|
||||||
import * as ep___blocking_delete from "./endpoints/blocking/delete.js";
|
import * as ep___blocking_delete from "./endpoints/blocking/delete.js";
|
||||||
import * as ep___blocking_list from "./endpoints/blocking/list.js";
|
import * as ep___blocking_list from "./endpoints/blocking/list.js";
|
||||||
import * as ep___channels_create from "./endpoints/channels/create.js";
|
|
||||||
import * as ep___channels_featured from "./endpoints/channels/featured.js";
|
|
||||||
import * as ep___channels_follow from "./endpoints/channels/follow.js";
|
|
||||||
import * as ep___channels_followed from "./endpoints/channels/followed.js";
|
|
||||||
import * as ep___channels_owned from "./endpoints/channels/owned.js";
|
|
||||||
import * as ep___channels_search from "./endpoints/channels/search.js";
|
|
||||||
import * as ep___channels_show from "./endpoints/channels/show.js";
|
|
||||||
import * as ep___channels_timeline from "./endpoints/channels/timeline.js";
|
|
||||||
import * as ep___channels_unfollow from "./endpoints/channels/unfollow.js";
|
|
||||||
import * as ep___channels_update from "./endpoints/channels/update.js";
|
|
||||||
import * as ep___charts_activeUsers from "./endpoints/charts/active-users.js";
|
import * as ep___charts_activeUsers from "./endpoints/charts/active-users.js";
|
||||||
import * as ep___charts_apRequest from "./endpoints/charts/ap-request.js";
|
import * as ep___charts_apRequest from "./endpoints/charts/ap-request.js";
|
||||||
import * as ep___charts_drive from "./endpoints/charts/drive.js";
|
import * as ep___charts_drive from "./endpoints/charts/drive.js";
|
||||||
|
@ -432,16 +422,6 @@ const eps = [
|
||||||
["blocking/create", ep___blocking_create],
|
["blocking/create", ep___blocking_create],
|
||||||
["blocking/delete", ep___blocking_delete],
|
["blocking/delete", ep___blocking_delete],
|
||||||
["blocking/list", ep___blocking_list],
|
["blocking/list", ep___blocking_list],
|
||||||
["channels/create", ep___channels_create],
|
|
||||||
["channels/featured", ep___channels_featured],
|
|
||||||
["channels/follow", ep___channels_follow],
|
|
||||||
["channels/followed", ep___channels_followed],
|
|
||||||
["channels/owned", ep___channels_owned],
|
|
||||||
["channels/search", ep___channels_search],
|
|
||||||
["channels/show", ep___channels_show],
|
|
||||||
["channels/timeline", ep___channels_timeline],
|
|
||||||
["channels/unfollow", ep___channels_unfollow],
|
|
||||||
["channels/update", ep___channels_update],
|
|
||||||
["charts/active-users", ep___charts_activeUsers],
|
["charts/active-users", ep___charts_activeUsers],
|
||||||
["charts/ap-request", ep___charts_apRequest],
|
["charts/ap-request", ep___charts_apRequest],
|
||||||
["charts/drive", ep___charts_drive],
|
["charts/drive", ep___charts_drive],
|
||||||
|
|
|
@ -1,68 +0,0 @@
|
||||||
import define from "../../define.js";
|
|
||||||
import { ApiError } from "../../error.js";
|
|
||||||
import { Channels, DriveFiles } from "@/models/index.js";
|
|
||||||
import type { Channel } from "@/models/entities/channel.js";
|
|
||||||
import { genId } from "@/misc/gen-id.js";
|
|
||||||
|
|
||||||
export const meta = {
|
|
||||||
tags: ["channels"],
|
|
||||||
|
|
||||||
requireCredential: true,
|
|
||||||
|
|
||||||
kind: "write:channels",
|
|
||||||
|
|
||||||
res: {
|
|
||||||
type: "object",
|
|
||||||
optional: false,
|
|
||||||
nullable: false,
|
|
||||||
ref: "Channel",
|
|
||||||
},
|
|
||||||
|
|
||||||
errors: {
|
|
||||||
noSuchFile: {
|
|
||||||
message: "No such file.",
|
|
||||||
code: "NO_SUCH_FILE",
|
|
||||||
id: "cd1e9f3e-5a12-4ab4-96f6-5d0a2cc32050",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const paramDef = {
|
|
||||||
type: "object",
|
|
||||||
properties: {
|
|
||||||
name: { type: "string", minLength: 1, maxLength: 128 },
|
|
||||||
description: {
|
|
||||||
type: "string",
|
|
||||||
nullable: true,
|
|
||||||
minLength: 1,
|
|
||||||
maxLength: 2048,
|
|
||||||
},
|
|
||||||
bannerId: { type: "string", format: "misskey:id", nullable: true },
|
|
||||||
},
|
|
||||||
required: ["name"],
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export default define(meta, paramDef, async (ps, user) => {
|
|
||||||
let banner = null;
|
|
||||||
if (ps.bannerId != null) {
|
|
||||||
banner = await DriveFiles.findOneBy({
|
|
||||||
id: ps.bannerId,
|
|
||||||
userId: user.id,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (banner == null) {
|
|
||||||
throw new ApiError(meta.errors.noSuchFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const channel = await Channels.insert({
|
|
||||||
id: genId(),
|
|
||||||
createdAt: new Date(),
|
|
||||||
userId: user.id,
|
|
||||||
name: ps.name,
|
|
||||||
description: ps.description || null,
|
|
||||||
bannerId: banner ? banner.id : null,
|
|
||||||
} as Channel).then((x) => Channels.findOneByOrFail(x.identifiers[0]));
|
|
||||||
|
|
||||||
return await Channels.pack(channel, user);
|
|
||||||
});
|
|
|
@ -1,37 +0,0 @@
|
||||||
import define from "../../define.js";
|
|
||||||
import { Channels } from "@/models/index.js";
|
|
||||||
|
|
||||||
export const meta = {
|
|
||||||
tags: ["channels"],
|
|
||||||
|
|
||||||
requireCredential: false,
|
|
||||||
requireCredentialPrivateMode: true,
|
|
||||||
|
|
||||||
res: {
|
|
||||||
type: "array",
|
|
||||||
optional: false,
|
|
||||||
nullable: false,
|
|
||||||
items: {
|
|
||||||
type: "object",
|
|
||||||
optional: false,
|
|
||||||
nullable: false,
|
|
||||||
ref: "Channel",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const paramDef = {
|
|
||||||
type: "object",
|
|
||||||
properties: {},
|
|
||||||
required: [],
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export default define(meta, paramDef, async (ps, me) => {
|
|
||||||
const query = Channels.createQueryBuilder("channel")
|
|
||||||
.where("channel.lastNotedAt IS NOT NULL")
|
|
||||||
.orderBy("channel.lastNotedAt", "DESC");
|
|
||||||
|
|
||||||
const channels = await query.take(10).getMany();
|
|
||||||
|
|
||||||
return await Promise.all(channels.map((x) => Channels.pack(x, me)));
|
|
||||||
});
|
|
|
@ -1,48 +0,0 @@
|
||||||
import define from "../../define.js";
|
|
||||||
import { ApiError } from "../../error.js";
|
|
||||||
import { Channels, ChannelFollowings } from "@/models/index.js";
|
|
||||||
import { genId } from "@/misc/gen-id.js";
|
|
||||||
import { publishUserEvent } from "@/services/stream.js";
|
|
||||||
|
|
||||||
export const meta = {
|
|
||||||
tags: ["channels"],
|
|
||||||
|
|
||||||
requireCredential: true,
|
|
||||||
|
|
||||||
kind: "write:channels",
|
|
||||||
|
|
||||||
errors: {
|
|
||||||
noSuchChannel: {
|
|
||||||
message: "No such channel.",
|
|
||||||
code: "NO_SUCH_CHANNEL",
|
|
||||||
id: "c0031718-d573-4e85-928e-10039f1fbb68",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const paramDef = {
|
|
||||||
type: "object",
|
|
||||||
properties: {
|
|
||||||
channelId: { type: "string", format: "misskey:id" },
|
|
||||||
},
|
|
||||||
required: ["channelId"],
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export default define(meta, paramDef, async (ps, user) => {
|
|
||||||
const channel = await Channels.findOneBy({
|
|
||||||
id: ps.channelId,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (channel == null) {
|
|
||||||
throw new ApiError(meta.errors.noSuchChannel);
|
|
||||||
}
|
|
||||||
|
|
||||||
await ChannelFollowings.insert({
|
|
||||||
id: genId(),
|
|
||||||
createdAt: new Date(),
|
|
||||||
followerId: user.id,
|
|
||||||
followeeId: channel.id,
|
|
||||||
});
|
|
||||||
|
|
||||||
publishUserEvent(user.id, "followChannel", channel);
|
|
||||||
});
|
|
|
@ -1,59 +0,0 @@
|
||||||
import define from "../../define.js";
|
|
||||||
import { Channels, ChannelFollowings } from "@/models/index.js";
|
|
||||||
|
|
||||||
export const meta = {
|
|
||||||
tags: ["channels", "account"],
|
|
||||||
|
|
||||||
requireCredential: true,
|
|
||||||
|
|
||||||
kind: "read:channels",
|
|
||||||
|
|
||||||
res: {
|
|
||||||
type: "array",
|
|
||||||
optional: false,
|
|
||||||
nullable: false,
|
|
||||||
items: {
|
|
||||||
type: "object",
|
|
||||||
optional: false,
|
|
||||||
nullable: false,
|
|
||||||
ref: "Channel",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const paramDef = {
|
|
||||||
type: "object",
|
|
||||||
properties: {
|
|
||||||
sinceId: { type: "string", format: "misskey:id" },
|
|
||||||
untilId: { type: "string", format: "misskey:id" },
|
|
||||||
limit: { type: "integer", minimum: 1, maximum: 100, default: 5 },
|
|
||||||
},
|
|
||||||
required: [],
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export default define(meta, paramDef, async (ps, me) => {
|
|
||||||
const query = ChannelFollowings.createQueryBuilder("following").andWhere({
|
|
||||||
followerId: me.id,
|
|
||||||
});
|
|
||||||
if (ps.sinceId) {
|
|
||||||
query.andWhere('following."followeeId" > :sinceId', {
|
|
||||||
sinceId: ps.sinceId,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (ps.untilId) {
|
|
||||||
query.andWhere('following."followeeId" < :untilId', {
|
|
||||||
untilId: ps.untilId,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (ps.sinceId && !ps.untilId) {
|
|
||||||
query.orderBy('following."followeeId"', "ASC");
|
|
||||||
} else {
|
|
||||||
query.orderBy('following."followeeId"', "DESC");
|
|
||||||
}
|
|
||||||
|
|
||||||
const followings = await query.take(ps.limit).getMany();
|
|
||||||
|
|
||||||
return await Promise.all(
|
|
||||||
followings.map((x) => Channels.pack(x.followeeId, me)),
|
|
||||||
);
|
|
||||||
});
|
|
|
@ -1,45 +0,0 @@
|
||||||
import define from "../../define.js";
|
|
||||||
import { Channels } from "@/models/index.js";
|
|
||||||
import { makePaginationQuery } from "../../common/make-pagination-query.js";
|
|
||||||
|
|
||||||
export const meta = {
|
|
||||||
tags: ["channels", "account"],
|
|
||||||
|
|
||||||
requireCredential: true,
|
|
||||||
|
|
||||||
kind: "read:channels",
|
|
||||||
|
|
||||||
res: {
|
|
||||||
type: "array",
|
|
||||||
optional: false,
|
|
||||||
nullable: false,
|
|
||||||
items: {
|
|
||||||
type: "object",
|
|
||||||
optional: false,
|
|
||||||
nullable: false,
|
|
||||||
ref: "Channel",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const paramDef = {
|
|
||||||
type: "object",
|
|
||||||
properties: {
|
|
||||||
sinceId: { type: "string", format: "misskey:id" },
|
|
||||||
untilId: { type: "string", format: "misskey:id" },
|
|
||||||
limit: { type: "integer", minimum: 1, maximum: 100, default: 5 },
|
|
||||||
},
|
|
||||||
required: [],
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export default define(meta, paramDef, async (ps, me) => {
|
|
||||||
const query = makePaginationQuery(
|
|
||||||
Channels.createQueryBuilder(),
|
|
||||||
ps.sinceId,
|
|
||||||
ps.untilId,
|
|
||||||
).andWhere({ userId: me.id });
|
|
||||||
|
|
||||||
const channels = await query.take(ps.limit).getMany();
|
|
||||||
|
|
||||||
return await Promise.all(channels.map((x) => Channels.pack(x, me)));
|
|
||||||
});
|
|
|
@ -1,69 +0,0 @@
|
||||||
import define from "../../define.js";
|
|
||||||
import { Brackets } from "typeorm";
|
|
||||||
import { Endpoint } from "@/server/api/endpoint-base.js";
|
|
||||||
import { makePaginationQuery } from "@/server/api/common/make-pagination-query.js";
|
|
||||||
import { Channels } from "@/models/index.js";
|
|
||||||
import { DI } from "@/di-symbols.js";
|
|
||||||
import { sqlLikeEscape } from "@/misc/sql-like-escape.js";
|
|
||||||
|
|
||||||
export const meta = {
|
|
||||||
tags: ["channels"],
|
|
||||||
|
|
||||||
requireCredential: false,
|
|
||||||
|
|
||||||
res: {
|
|
||||||
type: "array",
|
|
||||||
optional: false,
|
|
||||||
nullable: false,
|
|
||||||
items: {
|
|
||||||
type: "object",
|
|
||||||
optional: false,
|
|
||||||
nullable: false,
|
|
||||||
ref: "Channel",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const paramDef = {
|
|
||||||
type: "object",
|
|
||||||
properties: {
|
|
||||||
query: { type: "string" },
|
|
||||||
type: {
|
|
||||||
type: "string",
|
|
||||||
enum: ["nameAndDescription", "nameOnly"],
|
|
||||||
default: "nameAndDescription",
|
|
||||||
},
|
|
||||||
sinceId: { type: "string", format: "misskey:id" },
|
|
||||||
untilId: { type: "string", format: "misskey:id" },
|
|
||||||
limit: { type: "integer", minimum: 1, maximum: 100, default: 5 },
|
|
||||||
},
|
|
||||||
required: ["query"],
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export default define(meta, paramDef, async (ps, me) => {
|
|
||||||
const query = makePaginationQuery(
|
|
||||||
Channels.createQueryBuilder("channel"),
|
|
||||||
ps.sinceId,
|
|
||||||
ps.untilId,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (ps.type === "nameAndDescription") {
|
|
||||||
query.andWhere(
|
|
||||||
new Brackets((qb) => {
|
|
||||||
qb.where("channel.name ILIKE :q", {
|
|
||||||
q: `%${sqlLikeEscape(ps.query)}%`,
|
|
||||||
}).orWhere("channel.description ILIKE :q", {
|
|
||||||
q: `%${sqlLikeEscape(ps.query)}%`,
|
|
||||||
});
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
query.andWhere("channel.name ILIKE :q", {
|
|
||||||
q: `%${sqlLikeEscape(ps.query)}%`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const channels = await query.take(ps.limit).getMany();
|
|
||||||
|
|
||||||
return await Promise.all(channels.map((x) => Channels.pack(x, me)));
|
|
||||||
});
|
|
|
@ -1,45 +0,0 @@
|
||||||
import define from "../../define.js";
|
|
||||||
import { ApiError } from "../../error.js";
|
|
||||||
import { Channels } from "@/models/index.js";
|
|
||||||
|
|
||||||
export const meta = {
|
|
||||||
tags: ["channels"],
|
|
||||||
|
|
||||||
requireCredential: false,
|
|
||||||
requireCredentialPrivateMode: true,
|
|
||||||
|
|
||||||
res: {
|
|
||||||
type: "object",
|
|
||||||
optional: false,
|
|
||||||
nullable: false,
|
|
||||||
ref: "Channel",
|
|
||||||
},
|
|
||||||
|
|
||||||
errors: {
|
|
||||||
noSuchChannel: {
|
|
||||||
message: "No such channel.",
|
|
||||||
code: "NO_SUCH_CHANNEL",
|
|
||||||
id: "6f6c314b-7486-4897-8966-c04a66a02923",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const paramDef = {
|
|
||||||
type: "object",
|
|
||||||
properties: {
|
|
||||||
channelId: { type: "string", format: "misskey:id" },
|
|
||||||
},
|
|
||||||
required: ["channelId"],
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export default define(meta, paramDef, async (ps, me) => {
|
|
||||||
const channel = await Channels.findOneBy({
|
|
||||||
id: ps.channelId,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (channel == null) {
|
|
||||||
throw new ApiError(meta.errors.noSuchChannel);
|
|
||||||
}
|
|
||||||
|
|
||||||
return await Channels.pack(channel, me);
|
|
||||||
});
|
|
|
@ -1,84 +0,0 @@
|
||||||
import define from "../../define.js";
|
|
||||||
import { ApiError } from "../../error.js";
|
|
||||||
import { Notes, Channels } from "@/models/index.js";
|
|
||||||
import { makePaginationQuery } from "../../common/make-pagination-query.js";
|
|
||||||
import { activeUsersChart } from "@/services/chart/index.js";
|
|
||||||
|
|
||||||
export const meta = {
|
|
||||||
tags: ["notes", "channels"],
|
|
||||||
|
|
||||||
requireCredential: false,
|
|
||||||
requireCredentialPrivateMode: true,
|
|
||||||
|
|
||||||
res: {
|
|
||||||
type: "array",
|
|
||||||
optional: false,
|
|
||||||
nullable: false,
|
|
||||||
items: {
|
|
||||||
type: "object",
|
|
||||||
optional: false,
|
|
||||||
nullable: false,
|
|
||||||
ref: "Note",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
errors: {
|
|
||||||
noSuchChannel: {
|
|
||||||
message: "No such channel.",
|
|
||||||
code: "NO_SUCH_CHANNEL",
|
|
||||||
id: "4d0eeeba-a02c-4c3c-9966-ef60d38d2e7f",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const paramDef = {
|
|
||||||
type: "object",
|
|
||||||
properties: {
|
|
||||||
channelId: { type: "string", format: "misskey:id" },
|
|
||||||
limit: { type: "integer", minimum: 1, maximum: 100, default: 10 },
|
|
||||||
sinceId: { type: "string", format: "misskey:id" },
|
|
||||||
untilId: { type: "string", format: "misskey:id" },
|
|
||||||
sinceDate: { type: "integer" },
|
|
||||||
untilDate: { type: "integer" },
|
|
||||||
},
|
|
||||||
required: ["channelId"],
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export default define(meta, paramDef, async (ps, user) => {
|
|
||||||
const channel = await Channels.findOneBy({
|
|
||||||
id: ps.channelId,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (channel == null) {
|
|
||||||
throw new ApiError(meta.errors.noSuchChannel);
|
|
||||||
}
|
|
||||||
|
|
||||||
//#region Construct query
|
|
||||||
const query = makePaginationQuery(
|
|
||||||
Notes.createQueryBuilder("note"),
|
|
||||||
ps.sinceId,
|
|
||||||
ps.untilId,
|
|
||||||
ps.sinceDate,
|
|
||||||
ps.untilDate,
|
|
||||||
)
|
|
||||||
.andWhere("note.channelId = :channelId", { channelId: channel.id })
|
|
||||||
.innerJoinAndSelect("note.user", "user")
|
|
||||||
.leftJoinAndSelect("user.avatar", "avatar")
|
|
||||||
.leftJoinAndSelect("user.banner", "banner")
|
|
||||||
.leftJoinAndSelect("note.reply", "reply")
|
|
||||||
.leftJoinAndSelect("note.renote", "renote")
|
|
||||||
.leftJoinAndSelect("reply.user", "replyUser")
|
|
||||||
.leftJoinAndSelect("replyUser.avatar", "replyUserAvatar")
|
|
||||||
.leftJoinAndSelect("replyUser.banner", "replyUserBanner")
|
|
||||||
.leftJoinAndSelect("renote.user", "renoteUser")
|
|
||||||
.leftJoinAndSelect("renoteUser.avatar", "renoteUserAvatar")
|
|
||||||
.leftJoinAndSelect("renoteUser.banner", "renoteUserBanner")
|
|
||||||
.leftJoinAndSelect("note.channel", "channel");
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
const timeline = await query.take(ps.limit).getMany();
|
|
||||||
|
|
||||||
if (user) activeUsersChart.read(user);
|
|
||||||
|
|
||||||
return await Notes.packMany(timeline, user);
|
|
||||||
});
|
|
|
@ -1,45 +0,0 @@
|
||||||
import define from "../../define.js";
|
|
||||||
import { ApiError } from "../../error.js";
|
|
||||||
import { Channels, ChannelFollowings } from "@/models/index.js";
|
|
||||||
import { publishUserEvent } from "@/services/stream.js";
|
|
||||||
|
|
||||||
export const meta = {
|
|
||||||
tags: ["channels"],
|
|
||||||
|
|
||||||
requireCredential: true,
|
|
||||||
|
|
||||||
kind: "write:channels",
|
|
||||||
|
|
||||||
errors: {
|
|
||||||
noSuchChannel: {
|
|
||||||
message: "No such channel.",
|
|
||||||
code: "NO_SUCH_CHANNEL",
|
|
||||||
id: "19959ee9-0153-4c51-bbd9-a98c49dc59d6",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const paramDef = {
|
|
||||||
type: "object",
|
|
||||||
properties: {
|
|
||||||
channelId: { type: "string", format: "misskey:id" },
|
|
||||||
},
|
|
||||||
required: ["channelId"],
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export default define(meta, paramDef, async (ps, user) => {
|
|
||||||
const channel = await Channels.findOneBy({
|
|
||||||
id: ps.channelId,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (channel == null) {
|
|
||||||
throw new ApiError(meta.errors.noSuchChannel);
|
|
||||||
}
|
|
||||||
|
|
||||||
await ChannelFollowings.delete({
|
|
||||||
followerId: user.id,
|
|
||||||
followeeId: channel.id,
|
|
||||||
});
|
|
||||||
|
|
||||||
publishUserEvent(user.id, "unfollowChannel", channel);
|
|
||||||
});
|
|
|
@ -1,90 +0,0 @@
|
||||||
import define from "../../define.js";
|
|
||||||
import { ApiError } from "../../error.js";
|
|
||||||
import { Channels, DriveFiles } from "@/models/index.js";
|
|
||||||
|
|
||||||
export const meta = {
|
|
||||||
tags: ["channels"],
|
|
||||||
|
|
||||||
requireCredential: true,
|
|
||||||
|
|
||||||
kind: "write:channels",
|
|
||||||
|
|
||||||
res: {
|
|
||||||
type: "object",
|
|
||||||
optional: false,
|
|
||||||
nullable: false,
|
|
||||||
ref: "Channel",
|
|
||||||
},
|
|
||||||
|
|
||||||
errors: {
|
|
||||||
noSuchChannel: {
|
|
||||||
message: "No such channel.",
|
|
||||||
code: "NO_SUCH_CHANNEL",
|
|
||||||
id: "f9c5467f-d492-4c3c-9a8d-a70dacc86512",
|
|
||||||
},
|
|
||||||
|
|
||||||
accessDenied: {
|
|
||||||
message: "You do not have edit privilege of the channel.",
|
|
||||||
code: "ACCESS_DENIED",
|
|
||||||
id: "1fb7cb09-d46a-4fdf-b8df-057788cce513",
|
|
||||||
},
|
|
||||||
|
|
||||||
noSuchFile: {
|
|
||||||
message: "No such file.",
|
|
||||||
code: "NO_SUCH_FILE",
|
|
||||||
id: "e86c14a4-0da2-4032-8df3-e737a04c7f3b",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const paramDef = {
|
|
||||||
type: "object",
|
|
||||||
properties: {
|
|
||||||
channelId: { type: "string", format: "misskey:id" },
|
|
||||||
name: { type: "string", minLength: 1, maxLength: 128 },
|
|
||||||
description: {
|
|
||||||
type: "string",
|
|
||||||
nullable: true,
|
|
||||||
minLength: 1,
|
|
||||||
maxLength: 2048,
|
|
||||||
},
|
|
||||||
bannerId: { type: "string", format: "misskey:id", nullable: true },
|
|
||||||
},
|
|
||||||
required: ["channelId"],
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export default define(meta, paramDef, async (ps, me) => {
|
|
||||||
const channel = await Channels.findOneBy({
|
|
||||||
id: ps.channelId,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (channel == null) {
|
|
||||||
throw new ApiError(meta.errors.noSuchChannel);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (channel.userId !== me.id) {
|
|
||||||
throw new ApiError(meta.errors.accessDenied);
|
|
||||||
}
|
|
||||||
|
|
||||||
let banner = undefined;
|
|
||||||
if (ps.bannerId != null) {
|
|
||||||
banner = await DriveFiles.findOneBy({
|
|
||||||
id: ps.bannerId,
|
|
||||||
userId: me.id,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (banner == null) {
|
|
||||||
throw new ApiError(meta.errors.noSuchFile);
|
|
||||||
}
|
|
||||||
} else if (ps.bannerId === null) {
|
|
||||||
banner = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
await Channels.update(channel.id, {
|
|
||||||
...(ps.name !== undefined ? { name: ps.name } : {}),
|
|
||||||
...(ps.description !== undefined ? { description: ps.description } : {}),
|
|
||||||
...(banner ? { bannerId: banner.id } : {}),
|
|
||||||
});
|
|
||||||
|
|
||||||
return await Channels.pack(channel.id, me);
|
|
||||||
});
|
|
|
@ -1,22 +1,14 @@
|
||||||
import { In } from "typeorm";
|
import {In} from "typeorm";
|
||||||
import create from "@/services/note/create.js";
|
import create from "@/services/note/create.js";
|
||||||
import type { User } from "@/models/entities/user.js";
|
import type {User} from "@/models/entities/user.js";
|
||||||
import {
|
import {Blockings, DriveFiles, Notes, Users,} from "@/models/index.js";
|
||||||
Users,
|
import type {DriveFile} from "@/models/entities/drive-file.js";
|
||||||
DriveFiles,
|
import type {Note} from "@/models/entities/note.js";
|
||||||
Notes,
|
import {HOUR, MAX_NOTE_TEXT_LENGTH} from "@/const.js";
|
||||||
Channels,
|
import {noteVisibilities} from "../../../../types.js";
|
||||||
Blockings,
|
import {ApiError} from "../../error.js";
|
||||||
} from "@/models/index.js";
|
|
||||||
import type { DriveFile } from "@/models/entities/drive-file.js";
|
|
||||||
import type { Note } from "@/models/entities/note.js";
|
|
||||||
import type { Channel } from "@/models/entities/channel.js";
|
|
||||||
import { MAX_NOTE_TEXT_LENGTH } from "@/const.js";
|
|
||||||
import { noteVisibilities } from "../../../../types.js";
|
|
||||||
import { ApiError } from "../../error.js";
|
|
||||||
import define from "../../define.js";
|
import define from "../../define.js";
|
||||||
import { HOUR } from "@/const.js";
|
import {getNote} from "../../common/getters.js";
|
||||||
import { getNote } from "../../common/getters.js";
|
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ["notes"],
|
tags: ["notes"],
|
||||||
|
@ -268,16 +260,6 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
ps.poll.expiresAt = Date.now() + ps.poll.expiredAfter;
|
ps.poll.expiresAt = Date.now() + ps.poll.expiredAfter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let channel: Channel | null = null;
|
|
||||||
if (ps.channelId != null) {
|
|
||||||
channel = await Channels.findOneBy({ id: ps.channelId });
|
|
||||||
|
|
||||||
if (channel == null) {
|
|
||||||
throw new ApiError(meta.errors.noSuchChannel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a post
|
// Create a post
|
||||||
const note = await create(user, {
|
const note = await create(user, {
|
||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
|
@ -296,7 +278,6 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
localOnly: ps.localOnly,
|
localOnly: ps.localOnly,
|
||||||
visibility: ps.visibility,
|
visibility: ps.visibility,
|
||||||
visibleUsers,
|
visibleUsers,
|
||||||
channel,
|
|
||||||
apMentions: ps.noExtractMentions ? [] : undefined,
|
apMentions: ps.noExtractMentions ? [] : undefined,
|
||||||
apHashtags: ps.noExtractHashtags ? [] : undefined,
|
apHashtags: ps.noExtractHashtags ? [] : undefined,
|
||||||
apEmojis: ps.noExtractEmojis ? [] : undefined,
|
apEmojis: ps.noExtractEmojis ? [] : undefined,
|
||||||
|
|
|
@ -1,40 +1,28 @@
|
||||||
import { In } from "typeorm";
|
import {In} from "typeorm";
|
||||||
import create, { index } from "@/services/note/create.js";
|
import {extractMentionedUsers, index} from "@/services/note/create.js";
|
||||||
import type { IRemoteUser, User } from "@/models/entities/user.js";
|
import type {IRemoteUser, User} from "@/models/entities/user.js";
|
||||||
import {
|
import {Blockings, DriveFiles, NoteEdits, Notes, Polls, UserProfiles, Users,} from "@/models/index.js";
|
||||||
Users,
|
import type {DriveFile} from "@/models/entities/drive-file.js";
|
||||||
DriveFiles,
|
import type {IMentionedRemoteUsers, Note} from "@/models/entities/note.js";
|
||||||
Notes,
|
import {HOUR, MAX_NOTE_TEXT_LENGTH} from "@/const.js";
|
||||||
Channels,
|
import {noteVisibilities} from "../../../../types.js";
|
||||||
Blockings,
|
import {ApiError} from "../../error.js";
|
||||||
UserProfiles,
|
|
||||||
Polls,
|
|
||||||
NoteEdits,
|
|
||||||
} from "@/models/index.js";
|
|
||||||
import type { DriveFile } from "@/models/entities/drive-file.js";
|
|
||||||
import type { IMentionedRemoteUsers, Note } from "@/models/entities/note.js";
|
|
||||||
import type { Channel } from "@/models/entities/channel.js";
|
|
||||||
import { MAX_NOTE_TEXT_LENGTH } from "@/const.js";
|
|
||||||
import { noteVisibilities } from "../../../../types.js";
|
|
||||||
import { ApiError } from "../../error.js";
|
|
||||||
import define from "../../define.js";
|
import define from "../../define.js";
|
||||||
import { HOUR } from "@/const.js";
|
import {getNote} from "../../common/getters.js";
|
||||||
import { getNote } from "../../common/getters.js";
|
import {Poll} from "@/models/entities/poll.js";
|
||||||
import { Poll } from "@/models/entities/poll.js";
|
|
||||||
import * as mfm from "mfm-js";
|
import * as mfm from "mfm-js";
|
||||||
import { concat } from "@/prelude/array.js";
|
import {concat} from "@/prelude/array.js";
|
||||||
import { extractHashtags } from "@/misc/extract-hashtags.js";
|
import {extractHashtags} from "@/misc/extract-hashtags.js";
|
||||||
import { extractCustomEmojisFromMfm } from "@/misc/extract-custom-emojis-from-mfm.js";
|
import {extractCustomEmojisFromMfm} from "@/misc/extract-custom-emojis-from-mfm.js";
|
||||||
import { extractMentionedUsers } from "@/services/note/create.js";
|
import {genId} from "@/misc/gen-id.js";
|
||||||
import { genId } from "@/misc/gen-id.js";
|
import {publishNoteStream} from "@/services/stream.js";
|
||||||
import { publishNoteStream } from "@/services/stream.js";
|
|
||||||
import DeliverManager from "@/remote/activitypub/deliver-manager.js";
|
import DeliverManager from "@/remote/activitypub/deliver-manager.js";
|
||||||
import { renderActivity } from "@/remote/activitypub/renderer/index.js";
|
import {renderActivity} from "@/remote/activitypub/renderer/index.js";
|
||||||
import renderNote from "@/remote/activitypub/renderer/note.js";
|
import renderNote from "@/remote/activitypub/renderer/note.js";
|
||||||
import renderUpdate from "@/remote/activitypub/renderer/update.js";
|
import renderUpdate from "@/remote/activitypub/renderer/update.js";
|
||||||
import { deliverToRelays } from "@/services/relay.js";
|
import {deliverToRelays} from "@/services/relay.js";
|
||||||
// import { deliverQuestionUpdate } from "@/services/note/polls/update.js";
|
// import { deliverQuestionUpdate } from "@/services/note/polls/update.js";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import {fetchMeta} from "@/misc/fetch-meta.js";
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ["notes"],
|
tags: ["notes"],
|
||||||
|
@ -320,15 +308,6 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let channel: Channel | null = null;
|
|
||||||
if (ps.channelId != null) {
|
|
||||||
channel = await Channels.findOneBy({ id: ps.channelId });
|
|
||||||
|
|
||||||
if (channel == null) {
|
|
||||||
throw new ApiError(meta.errors.noSuchChannel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// enforce silent clients on server
|
// enforce silent clients on server
|
||||||
if (user.isSilenced && ps.visibility === "public" && ps.channelId == null) {
|
if (user.isSilenced && ps.visibility === "public" && ps.channelId == null) {
|
||||||
ps.visibility = "home";
|
ps.visibility = "home";
|
||||||
|
@ -546,9 +525,6 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
update.mentions = mentionedUserIds;
|
update.mentions = mentionedUserIds;
|
||||||
update.mentionedRemoteUsers = JSON.stringify(mentionedRemoteUsers);
|
update.mentionedRemoteUsers = JSON.stringify(mentionedRemoteUsers);
|
||||||
}
|
}
|
||||||
if (ps.channelId !== note.channelId) {
|
|
||||||
update.channelId = ps.channelId;
|
|
||||||
}
|
|
||||||
if (ps.replyId !== note.replyId) {
|
if (ps.replyId !== note.replyId) {
|
||||||
update.replyId = ps.replyId;
|
update.replyId = ps.replyId;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import {fetchMeta} from "@/misc/fetch-meta.js";
|
||||||
import { Notes } from "@/models/index.js";
|
import {Notes} from "@/models/index.js";
|
||||||
import { activeUsersChart } from "@/services/chart/index.js";
|
import {activeUsersChart} from "@/services/chart/index.js";
|
||||||
import define from "../../define.js";
|
import define from "../../define.js";
|
||||||
import { ApiError } from "../../error.js";
|
import {ApiError} from "../../error.js";
|
||||||
import { makePaginationQuery } from "../../common/make-pagination-query.js";
|
import {makePaginationQuery} from "../../common/make-pagination-query.js";
|
||||||
import { generateMutedUserQuery } from "../../common/generate-muted-user-query.js";
|
import {generateMutedUserQuery} from "../../common/generate-muted-user-query.js";
|
||||||
import { generateRepliesQuery } from "../../common/generate-replies-query.js";
|
import {generateRepliesQuery} from "../../common/generate-replies-query.js";
|
||||||
import { generateMutedNoteQuery } from "../../common/generate-muted-note-query.js";
|
import {generateMutedNoteQuery} from "../../common/generate-muted-note-query.js";
|
||||||
import { generateBlockedUserQuery } from "../../common/generate-block-query.js";
|
import {generateBlockedUserQuery} from "../../common/generate-block-query.js";
|
||||||
import { generateMutedUserRenotesQueryForNotes } from "../../common/generated-muted-renote-query.js";
|
import {generateMutedUserRenotesQueryForNotes} from "../../common/generated-muted-renote-query.js";
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ["notes"],
|
tags: ["notes"],
|
||||||
|
@ -79,7 +79,6 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
ps.untilDate,
|
ps.untilDate,
|
||||||
)
|
)
|
||||||
.andWhere("note.visibility = 'public'")
|
.andWhere("note.visibility = 'public'")
|
||||||
.andWhere("note.channelId IS NULL")
|
|
||||||
.innerJoinAndSelect("note.user", "user")
|
.innerJoinAndSelect("note.user", "user")
|
||||||
.leftJoinAndSelect("user.avatar", "avatar")
|
.leftJoinAndSelect("user.avatar", "avatar")
|
||||||
.leftJoinAndSelect("user.banner", "banner")
|
.leftJoinAndSelect("user.banner", "banner")
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
import { Brackets } from "typeorm";
|
import {Brackets} from "typeorm";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import {fetchMeta} from "@/misc/fetch-meta.js";
|
||||||
import { Followings, Notes } from "@/models/index.js";
|
import {Followings, Notes} from "@/models/index.js";
|
||||||
import { activeUsersChart } from "@/services/chart/index.js";
|
import {activeUsersChart} from "@/services/chart/index.js";
|
||||||
import define from "../../define.js";
|
import define from "../../define.js";
|
||||||
import { ApiError } from "../../error.js";
|
import {ApiError} from "../../error.js";
|
||||||
import { makePaginationQuery } from "../../common/make-pagination-query.js";
|
import {makePaginationQuery} from "../../common/make-pagination-query.js";
|
||||||
import { generateVisibilityQuery } from "../../common/generate-visibility-query.js";
|
import {generateVisibilityQuery} from "../../common/generate-visibility-query.js";
|
||||||
import { generateMutedUserQuery } from "../../common/generate-muted-user-query.js";
|
import {generateMutedUserQuery} from "../../common/generate-muted-user-query.js";
|
||||||
import { generateRepliesQuery } from "../../common/generate-replies-query.js";
|
import {generateRepliesQuery} from "../../common/generate-replies-query.js";
|
||||||
import { generateMutedNoteQuery } from "../../common/generate-muted-note-query.js";
|
import {generateMutedNoteQuery} from "../../common/generate-muted-note-query.js";
|
||||||
import { generateChannelQuery } from "../../common/generate-channel-query.js";
|
import {generateBlockedUserQuery} from "../../common/generate-block-query.js";
|
||||||
import { generateBlockedUserQuery } from "../../common/generate-block-query.js";
|
import {generateMutedUserRenotesQueryForNotes} from "../../common/generated-muted-renote-query.js";
|
||||||
import { generateMutedUserRenotesQueryForNotes } from "../../common/generated-muted-renote-query.js";
|
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ["notes"],
|
tags: ["notes"],
|
||||||
|
@ -108,7 +107,6 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
.leftJoinAndSelect("renoteUser.banner", "renoteUserBanner")
|
.leftJoinAndSelect("renoteUser.banner", "renoteUserBanner")
|
||||||
.setParameters(followingQuery.getParameters());
|
.setParameters(followingQuery.getParameters());
|
||||||
|
|
||||||
generateChannelQuery(query, user);
|
|
||||||
generateRepliesQuery(query, ps.withReplies, user);
|
generateRepliesQuery(query, ps.withReplies, user);
|
||||||
generateVisibilityQuery(query, user);
|
generateVisibilityQuery(query, user);
|
||||||
generateMutedUserQuery(query, user);
|
generateMutedUserQuery(query, user);
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
import { Brackets } from "typeorm";
|
import {Brackets} from "typeorm";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import {fetchMeta} from "@/misc/fetch-meta.js";
|
||||||
import { Notes, Users } from "@/models/index.js";
|
import {Notes} from "@/models/index.js";
|
||||||
import { activeUsersChart } from "@/services/chart/index.js";
|
import {activeUsersChart} from "@/services/chart/index.js";
|
||||||
import define from "../../define.js";
|
import define from "../../define.js";
|
||||||
import { ApiError } from "../../error.js";
|
import {ApiError} from "../../error.js";
|
||||||
import { generateMutedUserQuery } from "../../common/generate-muted-user-query.js";
|
import {generateMutedUserQuery} from "../../common/generate-muted-user-query.js";
|
||||||
import { makePaginationQuery } from "../../common/make-pagination-query.js";
|
import {makePaginationQuery} from "../../common/make-pagination-query.js";
|
||||||
import { generateVisibilityQuery } from "../../common/generate-visibility-query.js";
|
import {generateVisibilityQuery} from "../../common/generate-visibility-query.js";
|
||||||
import { generateRepliesQuery } from "../../common/generate-replies-query.js";
|
import {generateRepliesQuery} from "../../common/generate-replies-query.js";
|
||||||
import { generateMutedNoteQuery } from "../../common/generate-muted-note-query.js";
|
import {generateMutedNoteQuery} from "../../common/generate-muted-note-query.js";
|
||||||
import { generateChannelQuery } from "../../common/generate-channel-query.js";
|
import {generateBlockedUserQuery} from "../../common/generate-block-query.js";
|
||||||
import { generateBlockedUserQuery } from "../../common/generate-block-query.js";
|
import {generateMutedUserRenotesQueryForNotes} from "../../common/generated-muted-renote-query.js";
|
||||||
import { generateMutedUserRenotesQueryForNotes } from "../../common/generated-muted-renote-query.js";
|
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ["notes"],
|
tags: ["notes"],
|
||||||
|
@ -101,7 +100,6 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
.leftJoinAndSelect("renoteUser.avatar", "renoteUserAvatar")
|
.leftJoinAndSelect("renoteUser.avatar", "renoteUserAvatar")
|
||||||
.leftJoinAndSelect("renoteUser.banner", "renoteUserBanner");
|
.leftJoinAndSelect("renoteUser.banner", "renoteUserBanner");
|
||||||
|
|
||||||
generateChannelQuery(query, user);
|
|
||||||
generateRepliesQuery(query, ps.withReplies, user);
|
generateRepliesQuery(query, ps.withReplies, user);
|
||||||
generateVisibilityQuery(query, user);
|
generateVisibilityQuery(query, user);
|
||||||
if (user) generateMutedUserQuery(query, user);
|
if (user) generateMutedUserQuery(query, user);
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
import { Brackets } from "typeorm";
|
import {Brackets} from "typeorm";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import {fetchMeta} from "@/misc/fetch-meta.js";
|
||||||
import { Notes } from "@/models/index.js";
|
import {Notes} from "@/models/index.js";
|
||||||
import { activeUsersChart } from "@/services/chart/index.js";
|
import {activeUsersChart} from "@/services/chart/index.js";
|
||||||
import define from "../../define.js";
|
import define from "../../define.js";
|
||||||
import { ApiError } from "../../error.js";
|
import {ApiError} from "../../error.js";
|
||||||
import { generateMutedUserQuery } from "../../common/generate-muted-user-query.js";
|
import {generateMutedUserQuery} from "../../common/generate-muted-user-query.js";
|
||||||
import { makePaginationQuery } from "../../common/make-pagination-query.js";
|
import {makePaginationQuery} from "../../common/make-pagination-query.js";
|
||||||
import { generateVisibilityQuery } from "../../common/generate-visibility-query.js";
|
import {generateVisibilityQuery} from "../../common/generate-visibility-query.js";
|
||||||
import { generateRepliesQuery } from "../../common/generate-replies-query.js";
|
import {generateRepliesQuery} from "../../common/generate-replies-query.js";
|
||||||
import { generateMutedNoteQuery } from "../../common/generate-muted-note-query.js";
|
import {generateMutedNoteQuery} from "../../common/generate-muted-note-query.js";
|
||||||
import { generateChannelQuery } from "../../common/generate-channel-query.js";
|
import {generateBlockedUserQuery} from "../../common/generate-block-query.js";
|
||||||
import { generateBlockedUserQuery } from "../../common/generate-block-query.js";
|
import {generateMutedUserRenotesQueryForNotes} from "../../common/generated-muted-renote-query.js";
|
||||||
import { generateMutedUserRenotesQueryForNotes } from "../../common/generated-muted-renote-query.js";
|
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ["notes"],
|
tags: ["notes"],
|
||||||
|
@ -104,7 +103,6 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
.leftJoinAndSelect("renoteUser.avatar", "renoteUserAvatar")
|
.leftJoinAndSelect("renoteUser.avatar", "renoteUserAvatar")
|
||||||
.leftJoinAndSelect("renoteUser.banner", "renoteUserBanner");
|
.leftJoinAndSelect("renoteUser.banner", "renoteUserBanner");
|
||||||
|
|
||||||
generateChannelQuery(query, user);
|
|
||||||
generateRepliesQuery(query, ps.withReplies, user);
|
generateRepliesQuery(query, ps.withReplies, user);
|
||||||
generateVisibilityQuery(query, user);
|
generateVisibilityQuery(query, user);
|
||||||
if (user) generateMutedUserQuery(query, user);
|
if (user) generateMutedUserQuery(query, user);
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
import { Brackets } from "typeorm";
|
import {Brackets} from "typeorm";
|
||||||
import { Notes, Followings } from "@/models/index.js";
|
import {Followings, Notes} from "@/models/index.js";
|
||||||
import { activeUsersChart } from "@/services/chart/index.js";
|
import {activeUsersChart} from "@/services/chart/index.js";
|
||||||
import define from "../../define.js";
|
import define from "../../define.js";
|
||||||
import { makePaginationQuery } from "../../common/make-pagination-query.js";
|
import {makePaginationQuery} from "../../common/make-pagination-query.js";
|
||||||
import { generateVisibilityQuery } from "../../common/generate-visibility-query.js";
|
import {generateVisibilityQuery} from "../../common/generate-visibility-query.js";
|
||||||
import { generateMutedUserQuery } from "../../common/generate-muted-user-query.js";
|
import {generateMutedUserQuery} from "../../common/generate-muted-user-query.js";
|
||||||
import { generateRepliesQuery } from "../../common/generate-replies-query.js";
|
import {generateRepliesQuery} from "../../common/generate-replies-query.js";
|
||||||
import { generateMutedNoteQuery } from "../../common/generate-muted-note-query.js";
|
import {generateMutedNoteQuery} from "../../common/generate-muted-note-query.js";
|
||||||
import { generateChannelQuery } from "../../common/generate-channel-query.js";
|
import {generateBlockedUserQuery} from "../../common/generate-block-query.js";
|
||||||
import { generateBlockedUserQuery } from "../../common/generate-block-query.js";
|
import {generateMutedUserRenotesQueryForNotes} from "../../common/generated-muted-renote-query.js";
|
||||||
import { generateMutedUserRenotesQueryForNotes } from "../../common/generated-muted-renote-query.js";
|
import {ApiError} from "../../error.js";
|
||||||
import { ApiError } from "../../error.js";
|
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ["notes"],
|
tags: ["notes"],
|
||||||
|
@ -104,7 +103,6 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
.leftJoinAndSelect("renoteUser.banner", "renoteUserBanner")
|
.leftJoinAndSelect("renoteUser.banner", "renoteUserBanner")
|
||||||
.setParameters(followingQuery.getParameters());
|
.setParameters(followingQuery.getParameters());
|
||||||
|
|
||||||
generateChannelQuery(query, user);
|
|
||||||
generateRepliesQuery(query, ps.withReplies, user);
|
generateRepliesQuery(query, ps.withReplies, user);
|
||||||
generateVisibilityQuery(query, user);
|
generateVisibilityQuery(query, user);
|
||||||
generateMutedUserQuery(query, user);
|
generateMutedUserQuery(query, user);
|
||||||
|
|
|
@ -1,18 +1,23 @@
|
||||||
import type Connection from ".";
|
import type Connection from ".";
|
||||||
import type { Note } from "@/models/entities/note.js";
|
import type {Note} from "@/models/entities/note.js";
|
||||||
import { Notes } from "@/models/index.js";
|
import {Notes} from "@/models/index.js";
|
||||||
import type { Packed } from "@/misc/schema.js";
|
import type {Packed} from "@/misc/schema.js";
|
||||||
import { IdentifiableError } from "@/misc/identifiable-error.js";
|
import {IdentifiableError} from "@/misc/identifiable-error.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stream channel
|
* Stream channel
|
||||||
*/
|
*/
|
||||||
export default abstract class Channel {
|
export default abstract class Channel {
|
||||||
protected connection: Connection;
|
|
||||||
public id: string;
|
|
||||||
public abstract readonly chName: string;
|
|
||||||
public static readonly shouldShare: boolean;
|
public static readonly shouldShare: boolean;
|
||||||
public static readonly requireCredential: boolean;
|
public static readonly requireCredential: boolean;
|
||||||
|
public id: string;
|
||||||
|
public abstract readonly chName: string;
|
||||||
|
protected connection: Connection;
|
||||||
|
|
||||||
|
constructor(id: string, connection: Connection) {
|
||||||
|
this.id = id;
|
||||||
|
this.connection = connection;
|
||||||
|
}
|
||||||
|
|
||||||
protected get user() {
|
protected get user() {
|
||||||
return this.connection.user;
|
return this.connection.user;
|
||||||
|
@ -38,19 +43,10 @@ export default abstract class Channel {
|
||||||
return this.connection.blocking;
|
return this.connection.blocking;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected get followingChannels() {
|
|
||||||
return this.connection.followingChannels;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected get subscriber() {
|
protected get subscriber() {
|
||||||
return this.connection.subscriber;
|
return this.connection.subscriber;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(id: string, connection: Connection) {
|
|
||||||
this.id = id;
|
|
||||||
this.connection = connection;
|
|
||||||
}
|
|
||||||
|
|
||||||
public send(typeOrPayload: any, payload?: any) {
|
public send(typeOrPayload: any, payload?: any) {
|
||||||
const type = payload === undefined ? typeOrPayload.type : typeOrPayload;
|
const type = payload === undefined ? typeOrPayload.type : typeOrPayload;
|
||||||
const body = payload === undefined ? typeOrPayload.body : payload;
|
const body = payload === undefined ? typeOrPayload.body : payload;
|
||||||
|
@ -62,6 +58,12 @@ export default abstract class Channel {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract init(params: any): void;
|
||||||
|
|
||||||
|
public dispose?(): void;
|
||||||
|
|
||||||
|
public onMessage?(type: string, body: any): void;
|
||||||
|
|
||||||
protected withPackedNote(
|
protected withPackedNote(
|
||||||
callback: (note: Packed<"Note">) => void,
|
callback: (note: Packed<"Note">) => void,
|
||||||
): (Note) => void {
|
): (Note) => void {
|
||||||
|
@ -74,7 +76,6 @@ export default abstract class Channel {
|
||||||
note.reply = undefined;
|
note.reply = undefined;
|
||||||
note.renote = undefined;
|
note.renote = undefined;
|
||||||
note.user = undefined;
|
note.user = undefined;
|
||||||
note.channel = undefined;
|
|
||||||
|
|
||||||
const packed = await Notes.pack(note, this.user, { detail: true });
|
const packed = await Notes.pack(note, this.user, { detail: true });
|
||||||
|
|
||||||
|
@ -92,8 +93,4 @@ export default abstract class Channel {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract init(params: any): void;
|
|
||||||
public dispose?(): void;
|
|
||||||
public onMessage?(type: string, body: any): void;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,84 +0,0 @@
|
||||||
import Channel from "../channel.js";
|
|
||||||
import { Users } from "@/models/index.js";
|
|
||||||
import { isUserRelated } from "@/misc/is-user-related.js";
|
|
||||||
import type { User } from "@/models/entities/user.js";
|
|
||||||
import type { StreamMessages } from "../types.js";
|
|
||||||
import type { Packed } from "@/misc/schema.js";
|
|
||||||
|
|
||||||
export default class extends Channel {
|
|
||||||
public readonly chName = "channel";
|
|
||||||
public static shouldShare = false;
|
|
||||||
public static requireCredential = false;
|
|
||||||
private channelId: string;
|
|
||||||
private typers: Map<User["id"], Date> = new Map();
|
|
||||||
private emitTypersIntervalId: ReturnType<typeof setInterval>;
|
|
||||||
|
|
||||||
constructor(id: string, connection: Channel["connection"]) {
|
|
||||||
super(id, connection);
|
|
||||||
this.onNote = this.withPackedNote(this.onNote.bind(this));
|
|
||||||
this.emitTypers = this.emitTypers.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async init(params: any) {
|
|
||||||
this.channelId = params.channelId as string;
|
|
||||||
|
|
||||||
// Subscribe stream
|
|
||||||
this.subscriber.on("notesStream", this.onNote);
|
|
||||||
this.subscriber.on(`channelStream:${this.channelId}`, this.onEvent);
|
|
||||||
this.emitTypersIntervalId = setInterval(this.emitTypers, 5000);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async onNote(note: Packed<"Note">) {
|
|
||||||
if (note.visibility === "hidden") return;
|
|
||||||
if (note.channelId !== this.channelId) return;
|
|
||||||
|
|
||||||
// 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する
|
|
||||||
if (isUserRelated(note, this.muting)) return;
|
|
||||||
// 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する
|
|
||||||
if (isUserRelated(note, this.blocking)) return;
|
|
||||||
|
|
||||||
if (note.renote && !note.text && this.renoteMuting.has(note.userId)) return;
|
|
||||||
|
|
||||||
this.connection.cacheNote(note);
|
|
||||||
|
|
||||||
this.send("note", note);
|
|
||||||
}
|
|
||||||
|
|
||||||
private onEvent(data: StreamMessages["channel"]["payload"]) {
|
|
||||||
if (data.type === "typing") {
|
|
||||||
const id = data.body;
|
|
||||||
const begin = !this.typers.has(id);
|
|
||||||
this.typers.set(id, new Date());
|
|
||||||
if (begin) {
|
|
||||||
this.emitTypers();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async emitTypers() {
|
|
||||||
const now = new Date();
|
|
||||||
|
|
||||||
// Remove not typing users
|
|
||||||
for (const [userId, date] of Object.entries(this.typers)) {
|
|
||||||
if (now.getTime() - date.getTime() > 5000) this.typers.delete(userId);
|
|
||||||
}
|
|
||||||
|
|
||||||
const userIds = Array.from(this.typers.keys());
|
|
||||||
const users = await Users.packMany(userIds, null, {
|
|
||||||
detail: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.send({
|
|
||||||
type: "typers",
|
|
||||||
body: users,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public dispose() {
|
|
||||||
// Unsubscribe events
|
|
||||||
this.subscriber.off("notesStream", this.onNote);
|
|
||||||
this.subscriber.off(`channelStream:${this.channelId}`, this.onEvent);
|
|
||||||
|
|
||||||
clearInterval(this.emitTypersIntervalId);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +1,14 @@
|
||||||
import Channel from "../channel.js";
|
import Channel from "../channel.js";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import {fetchMeta} from "@/misc/fetch-meta.js";
|
||||||
import { getWordHardMute } from "@/misc/check-word-mute.js";
|
import {getWordHardMute} from "@/misc/check-word-mute.js";
|
||||||
import { isInstanceMuted } from "@/misc/is-instance-muted.js";
|
import {isInstanceMuted} from "@/misc/is-instance-muted.js";
|
||||||
import { isUserRelated } from "@/misc/is-user-related.js";
|
import {isUserRelated} from "@/misc/is-user-related.js";
|
||||||
import type { Packed } from "@/misc/schema.js";
|
import type {Packed} from "@/misc/schema.js";
|
||||||
|
|
||||||
export default class extends Channel {
|
export default class extends Channel {
|
||||||
public readonly chName = "globalTimeline";
|
|
||||||
public static shouldShare = true;
|
public static shouldShare = true;
|
||||||
public static requireCredential = false;
|
public static requireCredential = false;
|
||||||
|
public readonly chName = "globalTimeline";
|
||||||
private withReplies: boolean;
|
private withReplies: boolean;
|
||||||
|
|
||||||
constructor(id: string, connection: Channel["connection"]) {
|
constructor(id: string, connection: Channel["connection"]) {
|
||||||
|
@ -29,9 +29,13 @@ export default class extends Channel {
|
||||||
this.subscriber.on("notesStream", this.onNote);
|
this.subscriber.on("notesStream", this.onNote);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public dispose() {
|
||||||
|
// Unsubscribe events
|
||||||
|
this.subscriber.off("notesStream", this.onNote);
|
||||||
|
}
|
||||||
|
|
||||||
private async onNote(note: Packed<"Note">) {
|
private async onNote(note: Packed<"Note">) {
|
||||||
if (note.visibility !== "public") return;
|
if (note.visibility !== "public") return;
|
||||||
if (note.channelId != null) return;
|
|
||||||
|
|
||||||
// 関係ない返信は除外
|
// 関係ない返信は除外
|
||||||
if (note.reply && !this.withReplies) {
|
if (note.reply && !this.withReplies) {
|
||||||
|
@ -76,9 +80,4 @@ export default class extends Channel {
|
||||||
|
|
||||||
this.send("note", note);
|
this.send("note", note);
|
||||||
}
|
}
|
||||||
|
|
||||||
public dispose() {
|
|
||||||
// Unsubscribe events
|
|
||||||
this.subscriber.off("notesStream", this.onNote);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import Channel from "../channel.js";
|
import Channel from "../channel.js";
|
||||||
import { getWordHardMute } from "@/misc/check-word-mute.js";
|
import {getWordHardMute} from "@/misc/check-word-mute.js";
|
||||||
import { isUserRelated } from "@/misc/is-user-related.js";
|
import {isUserRelated} from "@/misc/is-user-related.js";
|
||||||
import { isInstanceMuted } from "@/misc/is-instance-muted.js";
|
import {isInstanceMuted} from "@/misc/is-instance-muted.js";
|
||||||
import type { Packed } from "@/misc/schema.js";
|
import type {Packed} from "@/misc/schema.js";
|
||||||
|
|
||||||
export default class extends Channel {
|
export default class extends Channel {
|
||||||
public readonly chName = "homeTimeline";
|
|
||||||
public static shouldShare = true;
|
public static shouldShare = true;
|
||||||
public static requireCredential = true;
|
public static requireCredential = true;
|
||||||
|
public readonly chName = "homeTimeline";
|
||||||
private withReplies: boolean;
|
private withReplies: boolean;
|
||||||
|
|
||||||
constructor(id: string, connection: Channel["connection"]) {
|
constructor(id: string, connection: Channel["connection"]) {
|
||||||
|
@ -22,15 +22,13 @@ export default class extends Channel {
|
||||||
this.subscriber.on("notesStream", this.onNote);
|
this.subscriber.on("notesStream", this.onNote);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public dispose() {
|
||||||
|
// Unsubscribe events
|
||||||
|
this.subscriber.off("notesStream", this.onNote);
|
||||||
|
}
|
||||||
|
|
||||||
private async onNote(note: Packed<"Note">) {
|
private async onNote(note: Packed<"Note">) {
|
||||||
if (note.visibility === "hidden") return;
|
if (note.visibility === "hidden") return;
|
||||||
if (note.channelId) {
|
|
||||||
if (!this.followingChannels.has(note.channelId)) return;
|
|
||||||
} else {
|
|
||||||
// その投稿のユーザーをフォローしていなかったら弾く
|
|
||||||
if (this.user!.id !== note.userId && !this.following.has(note.userId))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ignore notes from instances the user has muted
|
// Ignore notes from instances the user has muted
|
||||||
if (
|
if (
|
||||||
|
@ -75,9 +73,4 @@ export default class extends Channel {
|
||||||
|
|
||||||
this.send("note", note);
|
this.send("note", note);
|
||||||
}
|
}
|
||||||
|
|
||||||
public dispose() {
|
|
||||||
// Unsubscribe events
|
|
||||||
this.subscriber.off("notesStream", this.onNote);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import Channel from "../channel.js";
|
import Channel from "../channel.js";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import {fetchMeta} from "@/misc/fetch-meta.js";
|
||||||
import { getWordHardMute } from "@/misc/check-word-mute.js";
|
import {getWordHardMute} from "@/misc/check-word-mute.js";
|
||||||
import { isUserRelated } from "@/misc/is-user-related.js";
|
import {isUserRelated} from "@/misc/is-user-related.js";
|
||||||
import { isInstanceMuted } from "@/misc/is-instance-muted.js";
|
import {isInstanceMuted} from "@/misc/is-instance-muted.js";
|
||||||
import type { Packed } from "@/misc/schema.js";
|
import type {Packed} from "@/misc/schema.js";
|
||||||
|
|
||||||
export default class extends Channel {
|
export default class extends Channel {
|
||||||
public readonly chName = "hybridTimeline";
|
|
||||||
public static shouldShare = true;
|
public static shouldShare = true;
|
||||||
public static requireCredential = true;
|
public static requireCredential = true;
|
||||||
|
public readonly chName = "hybridTimeline";
|
||||||
private withReplies: boolean;
|
private withReplies: boolean;
|
||||||
|
|
||||||
constructor(id: string, connection: Channel["connection"]) {
|
constructor(id: string, connection: Channel["connection"]) {
|
||||||
|
@ -31,22 +31,13 @@ export default class extends Channel {
|
||||||
this.subscriber.on("notesStream", this.onNote);
|
this.subscriber.on("notesStream", this.onNote);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public dispose() {
|
||||||
|
// Unsubscribe events
|
||||||
|
this.subscriber.off("notesStream", this.onNote);
|
||||||
|
}
|
||||||
|
|
||||||
private async onNote(note: Packed<"Note">) {
|
private async onNote(note: Packed<"Note">) {
|
||||||
if (note.visibility === "hidden") return;
|
if (note.visibility === "hidden")
|
||||||
// チャンネルの投稿ではなく、自分自身の投稿 または
|
|
||||||
// チャンネルの投稿ではなく、その投稿のユーザーをフォローしている または
|
|
||||||
// チャンネルの投稿ではなく、全体公開のローカルの投稿 または
|
|
||||||
// フォローしているチャンネルの投稿 の場合だけ
|
|
||||||
if (
|
|
||||||
!(
|
|
||||||
(note.channelId == null && this.user!.id === note.userId) ||
|
|
||||||
(note.channelId == null && this.following.has(note.userId)) ||
|
|
||||||
(note.channelId == null &&
|
|
||||||
note.user.host == null &&
|
|
||||||
note.visibility === "public") ||
|
|
||||||
(note.channelId != null && this.followingChannels.has(note.channelId))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Ignore notes from instances the user has muted
|
// Ignore notes from instances the user has muted
|
||||||
|
@ -92,9 +83,4 @@ export default class extends Channel {
|
||||||
|
|
||||||
this.send("note", note);
|
this.send("note", note);
|
||||||
}
|
}
|
||||||
|
|
||||||
public dispose() {
|
|
||||||
// Unsubscribe events
|
|
||||||
this.subscriber.off("notesStream", this.onNote);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ import userList from "./user-list.js";
|
||||||
import antenna from "./antenna.js";
|
import antenna from "./antenna.js";
|
||||||
import drive from "./drive.js";
|
import drive from "./drive.js";
|
||||||
import hashtag from "./hashtag.js";
|
import hashtag from "./hashtag.js";
|
||||||
import channel from "./channel.js";
|
|
||||||
import admin from "./admin.js";
|
import admin from "./admin.js";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -26,6 +25,5 @@ export default {
|
||||||
antenna,
|
antenna,
|
||||||
drive,
|
drive,
|
||||||
hashtag,
|
hashtag,
|
||||||
channel,
|
|
||||||
admin,
|
admin,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import Channel from "../channel.js";
|
import Channel from "../channel.js";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import {fetchMeta} from "@/misc/fetch-meta.js";
|
||||||
import { getWordHardMute } from "@/misc/check-word-mute.js";
|
import {getWordHardMute} from "@/misc/check-word-mute.js";
|
||||||
import { isUserRelated } from "@/misc/is-user-related.js";
|
import {isUserRelated} from "@/misc/is-user-related.js";
|
||||||
import type { Packed } from "@/misc/schema.js";
|
import type {Packed} from "@/misc/schema.js";
|
||||||
|
|
||||||
export default class extends Channel {
|
export default class extends Channel {
|
||||||
public readonly chName = "localTimeline";
|
|
||||||
public static shouldShare = true;
|
public static shouldShare = true;
|
||||||
public static requireCredential = false;
|
public static requireCredential = false;
|
||||||
|
public readonly chName = "localTimeline";
|
||||||
private withReplies: boolean;
|
private withReplies: boolean;
|
||||||
|
|
||||||
constructor(id: string, connection: Channel["connection"]) {
|
constructor(id: string, connection: Channel["connection"]) {
|
||||||
|
@ -28,11 +28,14 @@ export default class extends Channel {
|
||||||
this.subscriber.on("notesStream", this.onNote);
|
this.subscriber.on("notesStream", this.onNote);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public dispose() {
|
||||||
|
// Unsubscribe events
|
||||||
|
this.subscriber.off("notesStream", this.onNote);
|
||||||
|
}
|
||||||
|
|
||||||
private async onNote(note: Packed<"Note">) {
|
private async onNote(note: Packed<"Note">) {
|
||||||
if (note.user.host !== null) return;
|
if (note.user.host !== null) return;
|
||||||
if (note.visibility !== "public") return;
|
if (note.visibility !== "public") return;
|
||||||
if (note.channelId != null && !this.followingChannels.has(note.channelId))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// 関係ない返信は除外
|
// 関係ない返信は除外
|
||||||
if (note.reply && !this.withReplies) {
|
if (note.reply && !this.withReplies) {
|
||||||
|
@ -68,9 +71,4 @@ export default class extends Channel {
|
||||||
|
|
||||||
this.send("note", note);
|
this.send("note", note);
|
||||||
}
|
}
|
||||||
|
|
||||||
public dispose() {
|
|
||||||
// Unsubscribe events
|
|
||||||
this.subscriber.off("notesStream", this.onNote);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,14 @@
|
||||||
import type { EventEmitter } from "events";
|
import type {EventEmitter} from "events";
|
||||||
import type * as websocket from "websocket";
|
import type * as websocket from "websocket";
|
||||||
import readNote from "@/services/note/read.js";
|
import type {User} from "@/models/entities/user.js";
|
||||||
import type { User } from "@/models/entities/user.js";
|
import {Blockings, Followings, Mutings, RenoteMutings, UserProfiles,} from "@/models/index.js";
|
||||||
import type { Channel as ChannelModel } from "@/models/entities/channel.js";
|
import type {AccessToken} from "@/models/entities/access-token.js";
|
||||||
import {
|
import type {UserProfile} from "@/models/entities/user-profile.js";
|
||||||
Followings,
|
import type {Packed} from "@/misc/schema.js";
|
||||||
Mutings,
|
import {readNotification} from "../common/read-notification.js";
|
||||||
RenoteMutings,
|
|
||||||
UserProfiles,
|
|
||||||
ChannelFollowings,
|
|
||||||
Blockings,
|
|
||||||
} from "@/models/index.js";
|
|
||||||
import type { AccessToken } from "@/models/entities/access-token.js";
|
|
||||||
import type { UserProfile } from "@/models/entities/user-profile.js";
|
|
||||||
import type { UserGroup } from "@/models/entities/user-group.js";
|
|
||||||
import type { Packed } from "@/misc/schema.js";
|
|
||||||
import { readNotification } from "../common/read-notification.js";
|
|
||||||
import channels from "./channels/index.js";
|
import channels from "./channels/index.js";
|
||||||
import type Channel from "./channel.js";
|
import type Channel from "./channel.js";
|
||||||
import type { StreamEventEmitter, StreamMessages } from "./types.js";
|
import type {StreamEventEmitter, StreamMessages} from "./types.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main stream connection
|
* Main stream connection
|
||||||
|
@ -30,14 +20,12 @@ export default class Connection {
|
||||||
public muting: Set<User["id"]> = new Set();
|
public muting: Set<User["id"]> = new Set();
|
||||||
public renoteMuting: Set<User["id"]> = new Set();
|
public renoteMuting: Set<User["id"]> = new Set();
|
||||||
public blocking: Set<User["id"]> = new Set(); // "被"blocking
|
public blocking: Set<User["id"]> = new Set(); // "被"blocking
|
||||||
public followingChannels: Set<ChannelModel["id"]> = new Set();
|
|
||||||
public token?: AccessToken;
|
public token?: AccessToken;
|
||||||
private wsConnection: websocket.connection;
|
|
||||||
public subscriber: StreamEventEmitter;
|
public subscriber: StreamEventEmitter;
|
||||||
|
private wsConnection: websocket.connection;
|
||||||
private channels: Channel[] = [];
|
private channels: Channel[] = [];
|
||||||
private subscribingNotes: Map<string, number> = new Map();
|
private subscribingNotes: Map<string, number> = new Map();
|
||||||
private cachedNotes: Packed<"Note">[] = [];
|
private cachedNotes: Packed<"Note">[] = [];
|
||||||
private isMastodonCompatible: boolean = false;
|
|
||||||
private host: string;
|
private host: string;
|
||||||
private accessToken: string;
|
private accessToken: string;
|
||||||
private currentSubscribe: string[][] = [];
|
private currentSubscribe: string[][] = [];
|
||||||
|
@ -75,7 +63,6 @@ export default class Connection {
|
||||||
this.updateMuting();
|
this.updateMuting();
|
||||||
this.updateRenoteMuting();
|
this.updateRenoteMuting();
|
||||||
this.updateBlocking();
|
this.updateBlocking();
|
||||||
this.updateFollowingChannels();
|
|
||||||
this.updateUserProfile();
|
this.updateUserProfile();
|
||||||
|
|
||||||
this.subscriber.on(`user:${this.user.id}`, this.onUserEvent);
|
this.subscriber.on(`user:${this.user.id}`, this.onUserEvent);
|
||||||
|
@ -89,6 +76,91 @@ export default class Connection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public cacheNote(note: Packed<"Note">) {
|
||||||
|
const add = (note: Packed<"Note">) => {
|
||||||
|
const existIndex = this.cachedNotes.findIndex((n) => n.id === note.id);
|
||||||
|
if (existIndex > -1) {
|
||||||
|
this.cachedNotes[existIndex] = note;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.cachedNotes.unshift(note);
|
||||||
|
if (this.cachedNotes.length > 32) {
|
||||||
|
this.cachedNotes.splice(32);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
add(note);
|
||||||
|
if (note.reply) add(note.reply);
|
||||||
|
if (note.renote) add(note.renote);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* クライアントにメッセージ送信
|
||||||
|
*/
|
||||||
|
public sendMessageToWs(type: string, payload: any) {
|
||||||
|
this.wsConnection.send(
|
||||||
|
JSON.stringify({
|
||||||
|
type: type,
|
||||||
|
body: payload,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* チャンネルに接続
|
||||||
|
*/
|
||||||
|
public connectChannel(
|
||||||
|
id: string,
|
||||||
|
params: any,
|
||||||
|
channel: string,
|
||||||
|
pong = false,
|
||||||
|
) {
|
||||||
|
if ((channels as any)[channel].requireCredential && this.user == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 共有可能チャンネルに接続しようとしていて、かつそのチャンネルに既に接続していたら無意味なので無視
|
||||||
|
if (
|
||||||
|
(channels as any)[channel].shouldShare &&
|
||||||
|
this.channels.some((c) => c.chName === channel)
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ch: Channel = new (channels as any)[channel](id, this);
|
||||||
|
this.channels.push(ch);
|
||||||
|
ch.init(params);
|
||||||
|
|
||||||
|
if (pong) {
|
||||||
|
this.sendMessageToWs("connected", {
|
||||||
|
id: id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* チャンネルから切断
|
||||||
|
* @param id チャンネルコネクションID
|
||||||
|
*/
|
||||||
|
public disconnectChannel(id: string) {
|
||||||
|
const channel = this.channels.find((c) => c.id === id);
|
||||||
|
|
||||||
|
if (channel) {
|
||||||
|
if (channel.dispose) channel.dispose();
|
||||||
|
this.channels = this.channels.filter((c) => c.id !== id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ストリームが切れたとき
|
||||||
|
*/
|
||||||
|
public dispose() {
|
||||||
|
for (const c of this.channels.filter((c) => c.dispose)) {
|
||||||
|
if (c.dispose) c.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private onUserEvent(data: StreamMessages["user"]["payload"]) {
|
private onUserEvent(data: StreamMessages["user"]["payload"]) {
|
||||||
// { type, body }と展開するとそれぞれ型が分離してしまう
|
// { type, body }と展開するとそれぞれ型が分離してしまう
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
|
@ -111,14 +183,6 @@ export default class Connection {
|
||||||
// TODO: renote mute events
|
// TODO: renote mute events
|
||||||
// TODO: block events
|
// TODO: block events
|
||||||
|
|
||||||
case "followChannel":
|
|
||||||
this.followingChannels.add(data.body.id);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "unfollowChannel":
|
|
||||||
this.followingChannels.delete(data.body.id);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "updateUserProfile":
|
case "updateUserProfile":
|
||||||
this.userProfile = data.body;
|
this.userProfile = data.body;
|
||||||
break;
|
break;
|
||||||
|
@ -162,7 +226,6 @@ export default class Connection {
|
||||||
break; // alias
|
break; // alias
|
||||||
case "sr":
|
case "sr":
|
||||||
this.onSubscribeNote(body);
|
this.onSubscribeNote(body);
|
||||||
this.readNote(body);
|
|
||||||
break;
|
break;
|
||||||
case "unsubNote":
|
case "unsubNote":
|
||||||
this.onUnsubscribeNote(body);
|
this.onUnsubscribeNote(body);
|
||||||
|
@ -190,39 +253,6 @@ export default class Connection {
|
||||||
this.sendMessageToWs(data.type, data.body);
|
this.sendMessageToWs(data.type, data.body);
|
||||||
}
|
}
|
||||||
|
|
||||||
public cacheNote(note: Packed<"Note">) {
|
|
||||||
const add = (note: Packed<"Note">) => {
|
|
||||||
const existIndex = this.cachedNotes.findIndex((n) => n.id === note.id);
|
|
||||||
if (existIndex > -1) {
|
|
||||||
this.cachedNotes[existIndex] = note;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.cachedNotes.unshift(note);
|
|
||||||
if (this.cachedNotes.length > 32) {
|
|
||||||
this.cachedNotes.splice(32);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
add(note);
|
|
||||||
if (note.reply) add(note.reply);
|
|
||||||
if (note.renote) add(note.renote);
|
|
||||||
}
|
|
||||||
|
|
||||||
private readNote(body: any) {
|
|
||||||
const id = body.id;
|
|
||||||
|
|
||||||
const note = this.cachedNotes.find((n) => n.id === id);
|
|
||||||
if (note == null) return;
|
|
||||||
|
|
||||||
if (this.user && note.userId !== this.user.id) {
|
|
||||||
readNote(this.user.id, [note], {
|
|
||||||
following: this.following,
|
|
||||||
followingChannels: this.followingChannels,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private onReadNotification(payload: any) {
|
private onReadNotification(payload: any) {
|
||||||
if (!payload.id) return;
|
if (!payload.id) return;
|
||||||
readNotification(this.user!.id, [payload.id]);
|
readNotification(this.user!.id, [payload.id]);
|
||||||
|
@ -281,63 +311,6 @@ export default class Connection {
|
||||||
this.disconnectChannel(id);
|
this.disconnectChannel(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* クライアントにメッセージ送信
|
|
||||||
*/
|
|
||||||
public sendMessageToWs(type: string, payload: any) {
|
|
||||||
this.wsConnection.send(
|
|
||||||
JSON.stringify({
|
|
||||||
type: type,
|
|
||||||
body: payload,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* チャンネルに接続
|
|
||||||
*/
|
|
||||||
public connectChannel(
|
|
||||||
id: string,
|
|
||||||
params: any,
|
|
||||||
channel: string,
|
|
||||||
pong = false,
|
|
||||||
) {
|
|
||||||
if ((channels as any)[channel].requireCredential && this.user == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 共有可能チャンネルに接続しようとしていて、かつそのチャンネルに既に接続していたら無意味なので無視
|
|
||||||
if (
|
|
||||||
(channels as any)[channel].shouldShare &&
|
|
||||||
this.channels.some((c) => c.chName === channel)
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ch: Channel = new (channels as any)[channel](id, this);
|
|
||||||
this.channels.push(ch);
|
|
||||||
ch.init(params);
|
|
||||||
|
|
||||||
if (pong) {
|
|
||||||
this.sendMessageToWs("connected", {
|
|
||||||
id: id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* チャンネルから切断
|
|
||||||
* @param id チャンネルコネクションID
|
|
||||||
*/
|
|
||||||
public disconnectChannel(id: string) {
|
|
||||||
const channel = this.channels.find((c) => c.id === id);
|
|
||||||
|
|
||||||
if (channel) {
|
|
||||||
if (channel.dispose) channel.dispose();
|
|
||||||
this.channels = this.channels.filter((c) => c.id !== id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* チャンネルへメッセージ送信要求時
|
* チャンネルへメッセージ送信要求時
|
||||||
* @param data メッセージ
|
* @param data メッセージ
|
||||||
|
@ -394,31 +367,9 @@ export default class Connection {
|
||||||
this.blocking = new Set<string>(blockings.map((x) => x.blockerId));
|
this.blocking = new Set<string>(blockings.map((x) => x.blockerId));
|
||||||
}
|
}
|
||||||
|
|
||||||
private async updateFollowingChannels() {
|
|
||||||
const followings = await ChannelFollowings.find({
|
|
||||||
where: {
|
|
||||||
followerId: this.user!.id,
|
|
||||||
},
|
|
||||||
select: ["followeeId"],
|
|
||||||
});
|
|
||||||
|
|
||||||
this.followingChannels = new Set<string>(
|
|
||||||
followings.map((x) => x.followeeId),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async updateUserProfile() {
|
private async updateUserProfile() {
|
||||||
this.userProfile = await UserProfiles.findOneBy({
|
this.userProfile = await UserProfiles.findOneBy({
|
||||||
userId: this.user!.id,
|
userId: this.user!.id,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* ストリームが切れたとき
|
|
||||||
*/
|
|
||||||
public dispose() {
|
|
||||||
for (const c of this.channels.filter((c) => c.dispose)) {
|
|
||||||
if (c.dispose) c.dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,17 @@
|
||||||
import type { EventEmitter } from "events";
|
import type {EventEmitter} from "events";
|
||||||
import type Emitter from "strict-event-emitter-types";
|
import type Emitter from "strict-event-emitter-types";
|
||||||
import type { Channel } from "@/models/entities/channel.js";
|
import type {User} from "@/models/entities/user.js";
|
||||||
import type { User } from "@/models/entities/user.js";
|
import type {UserProfile} from "@/models/entities/user-profile.js";
|
||||||
import type { UserProfile } from "@/models/entities/user-profile.js";
|
import type {Note} from "@/models/entities/note.js";
|
||||||
import type { Note } from "@/models/entities/note.js";
|
import type {Antenna} from "@/models/entities/antenna.js";
|
||||||
import type { Antenna } from "@/models/entities/antenna.js";
|
import type {DriveFile} from "@/models/entities/drive-file.js";
|
||||||
import type { DriveFile } from "@/models/entities/drive-file.js";
|
import type {DriveFolder} from "@/models/entities/drive-folder.js";
|
||||||
import type { DriveFolder } from "@/models/entities/drive-folder.js";
|
import type {UserList} from "@/models/entities/user-list.js";
|
||||||
import type { UserList } from "@/models/entities/user-list.js";
|
import type {AbuseUserReport} from "@/models/entities/abuse-user-report.js";
|
||||||
import type { UserGroup } from "@/models/entities/user-group.js";
|
import type {Signin} from "@/models/entities/signin.js";
|
||||||
import type { AbuseUserReport } from "@/models/entities/abuse-user-report.js";
|
import type {Page} from "@/models/entities/page.js";
|
||||||
import type { Signin } from "@/models/entities/signin.js";
|
import type {Packed} from "@/misc/schema.js";
|
||||||
import type { Page } from "@/models/entities/page.js";
|
import type {Webhook} from "@/models/entities/webhook";
|
||||||
import type { Packed } from "@/misc/schema.js";
|
|
||||||
import type { Webhook } from "@/models/entities/webhook";
|
|
||||||
|
|
||||||
//#region Stream type-body definitions
|
//#region Stream type-body definitions
|
||||||
export interface InternalStreamTypes {
|
export interface InternalStreamTypes {
|
||||||
|
@ -56,8 +54,6 @@ export interface BroadcastTypes {
|
||||||
|
|
||||||
export interface UserStreamTypes {
|
export interface UserStreamTypes {
|
||||||
terminate: Record<string, unknown>;
|
terminate: Record<string, unknown>;
|
||||||
followChannel: Channel;
|
|
||||||
unfollowChannel: Channel;
|
|
||||||
updateUserProfile: UserProfile;
|
updateUserProfile: UserProfile;
|
||||||
mute: User;
|
mute: User;
|
||||||
unmute: User;
|
unmute: User;
|
||||||
|
@ -207,10 +203,6 @@ export type StreamMessages = {
|
||||||
name: `noteStream:${Note["id"]}`;
|
name: `noteStream:${Note["id"]}`;
|
||||||
payload: EventUnionFromDictionary<NoteStreamEventTypes>;
|
payload: EventUnionFromDictionary<NoteStreamEventTypes>;
|
||||||
};
|
};
|
||||||
channel: {
|
|
||||||
name: `channelStream:${Channel["id"]}`;
|
|
||||||
payload: EventUnionFromDictionary<ChannelStreamTypes>;
|
|
||||||
};
|
|
||||||
userList: {
|
userList: {
|
||||||
name: `userListStream:${UserList["id"]}`;
|
name: `userListStream:${UserList["id"]}`;
|
||||||
payload: EventUnionFromDictionary<UserListStreamTypes>;
|
payload: EventUnionFromDictionary<UserListStreamTypes>;
|
||||||
|
|
|
@ -1,74 +1,59 @@
|
||||||
import * as mfm from "mfm-js";
|
import * as mfm from "mfm-js";
|
||||||
import es from "../../db/elasticsearch.js";
|
import es from "../../db/elasticsearch.js";
|
||||||
import sonic from "../../db/sonic.js";
|
import sonic from "../../db/sonic.js";
|
||||||
import {
|
import {publishMainStream, publishNotesStream, publishNoteStream,} from "@/services/stream.js";
|
||||||
publishMainStream,
|
|
||||||
publishNotesStream,
|
|
||||||
publishNoteStream,
|
|
||||||
} from "@/services/stream.js";
|
|
||||||
import DeliverManager from "@/remote/activitypub/deliver-manager.js";
|
import DeliverManager from "@/remote/activitypub/deliver-manager.js";
|
||||||
import renderNote from "@/remote/activitypub/renderer/note.js";
|
import renderNote from "@/remote/activitypub/renderer/note.js";
|
||||||
import renderCreate from "@/remote/activitypub/renderer/create.js";
|
import renderCreate from "@/remote/activitypub/renderer/create.js";
|
||||||
import renderAnnounce from "@/remote/activitypub/renderer/announce.js";
|
import renderAnnounce from "@/remote/activitypub/renderer/announce.js";
|
||||||
import { renderActivity } from "@/remote/activitypub/renderer/index.js";
|
import {renderActivity} from "@/remote/activitypub/renderer/index.js";
|
||||||
import { resolveUser } from "@/remote/resolve-user.js";
|
import {resolveUser} from "@/remote/resolve-user.js";
|
||||||
import config from "@/config/index.js";
|
import config from "@/config/index.js";
|
||||||
import { updateHashtags } from "../update-hashtag.js";
|
import {updateHashtags} from "../update-hashtag.js";
|
||||||
import { concat } from "@/prelude/array.js";
|
import {concat} from "@/prelude/array.js";
|
||||||
import { insertNoteUnread } from "@/services/note/unread.js";
|
import {insertNoteUnread} from "@/services/note/unread.js";
|
||||||
import { registerOrFetchInstanceDoc } from "../register-or-fetch-instance-doc.js";
|
import {registerOrFetchInstanceDoc} from "../register-or-fetch-instance-doc.js";
|
||||||
import { extractMentions } from "@/misc/extract-mentions.js";
|
import {extractMentions} from "@/misc/extract-mentions.js";
|
||||||
import { extractCustomEmojisFromMfm } from "@/misc/extract-custom-emojis-from-mfm.js";
|
import {extractCustomEmojisFromMfm} from "@/misc/extract-custom-emojis-from-mfm.js";
|
||||||
import { extractHashtags } from "@/misc/extract-hashtags.js";
|
import {extractHashtags} from "@/misc/extract-hashtags.js";
|
||||||
import type { IMentionedRemoteUsers } from "@/models/entities/note.js";
|
import type {IMentionedRemoteUsers} from "@/models/entities/note.js";
|
||||||
import { Note } from "@/models/entities/note.js";
|
import {Note} from "@/models/entities/note.js";
|
||||||
import {
|
import {
|
||||||
Mutings,
|
|
||||||
Users,
|
|
||||||
NoteWatchings,
|
|
||||||
Notes,
|
|
||||||
Instances,
|
Instances,
|
||||||
UserProfiles,
|
|
||||||
Antennas,
|
|
||||||
Followings,
|
|
||||||
MutedNotes,
|
MutedNotes,
|
||||||
Channels,
|
Mutings,
|
||||||
ChannelFollowings,
|
Notes,
|
||||||
Blockings,
|
|
||||||
NoteThreadMutings,
|
NoteThreadMutings,
|
||||||
|
NoteWatchings,
|
||||||
|
UserProfiles,
|
||||||
|
Users,
|
||||||
} from "@/models/index.js";
|
} from "@/models/index.js";
|
||||||
import type { DriveFile } from "@/models/entities/drive-file.js";
|
import type {DriveFile} from "@/models/entities/drive-file.js";
|
||||||
import type { App } from "@/models/entities/app.js";
|
import type {App} from "@/models/entities/app.js";
|
||||||
import { Not, In, IsNull } from "typeorm";
|
import {In, Not} from "typeorm";
|
||||||
import type { User, ILocalUser, IRemoteUser } from "@/models/entities/user.js";
|
import type {ILocalUser, IRemoteUser, User} from "@/models/entities/user.js";
|
||||||
import { genId } from "@/misc/gen-id.js";
|
import {genId} from "@/misc/gen-id.js";
|
||||||
import {
|
import {activeUsersChart, instanceChart, notesChart, perUserNotesChart,} from "@/services/chart/index.js";
|
||||||
notesChart,
|
import type {IPoll} from "@/models/entities/poll.js";
|
||||||
perUserNotesChart,
|
import {Poll} from "@/models/entities/poll.js";
|
||||||
activeUsersChart,
|
import {createNotification} from "../create-notification.js";
|
||||||
instanceChart,
|
import {isDuplicateKeyValueError} from "@/misc/is-duplicate-key-value-error.js";
|
||||||
} from "@/services/chart/index.js";
|
import {checkHitAntenna} from "@/misc/check-hit-antenna.js";
|
||||||
import type { IPoll } from "@/models/entities/poll.js";
|
import {getWordHardMute} from "@/misc/check-word-mute.js";
|
||||||
import { Poll } from "@/models/entities/poll.js";
|
import {addNoteToAntenna} from "../add-note-to-antenna.js";
|
||||||
import { createNotification } from "../create-notification.js";
|
import {countSameRenotes} from "@/misc/count-same-renotes.js";
|
||||||
import { isDuplicateKeyValueError } from "@/misc/is-duplicate-key-value-error.js";
|
import {deliverToRelays, getCachedRelays} from "../relay.js";
|
||||||
import { checkHitAntenna } from "@/misc/check-hit-antenna.js";
|
import {normalizeForSearch} from "@/misc/normalize-for-search.js";
|
||||||
import { getWordHardMute } from "@/misc/check-word-mute.js";
|
import {getAntennas} from "@/misc/antenna-cache.js";
|
||||||
import { addNoteToAntenna } from "../add-note-to-antenna.js";
|
import {endedPollNotificationQueue} from "@/queue/queues.js";
|
||||||
import { countSameRenotes } from "@/misc/count-same-renotes.js";
|
import {webhookDeliver} from "@/queue/index.js";
|
||||||
import { deliverToRelays, getCachedRelays } from "../relay.js";
|
import {Cache} from "@/misc/cache.js";
|
||||||
import type { Channel } from "@/models/entities/channel.js";
|
import type {UserProfile} from "@/models/entities/user-profile.js";
|
||||||
import { normalizeForSearch } from "@/misc/normalize-for-search.js";
|
import {db} from "@/db/postgre.js";
|
||||||
import { getAntennas } from "@/misc/antenna-cache.js";
|
import {getActiveWebhooks} from "@/misc/webhook-cache.js";
|
||||||
import { endedPollNotificationQueue } from "@/queue/queues.js";
|
import {shouldSilenceInstance} from "@/misc/should-block-instance.js";
|
||||||
import { webhookDeliver } from "@/queue/index.js";
|
|
||||||
import { Cache } from "@/misc/cache.js";
|
|
||||||
import type { UserProfile } from "@/models/entities/user-profile.js";
|
|
||||||
import { db } from "@/db/postgre.js";
|
|
||||||
import { getActiveWebhooks } from "@/misc/webhook-cache.js";
|
|
||||||
import { shouldSilenceInstance } from "@/misc/should-block-instance.js";
|
|
||||||
import meilisearch from "../../db/meilisearch.js";
|
import meilisearch from "../../db/meilisearch.js";
|
||||||
import { redisClient } from "@/db/redis.js";
|
import {redisClient} from "@/db/redis.js";
|
||||||
|
|
||||||
const mutedWordsCache = new Cache<
|
const mutedWordsCache = new Cache<
|
||||||
{ userId: UserProfile["userId"]; mutedWords: UserProfile["mutedWords"] }[]
|
{ userId: UserProfile["userId"]; mutedWords: UserProfile["mutedWords"] }[]
|
||||||
|
@ -149,7 +134,6 @@ type Option = {
|
||||||
cw?: string | null;
|
cw?: string | null;
|
||||||
visibility?: string;
|
visibility?: string;
|
||||||
visibleUsers?: MinimumUser[] | null;
|
visibleUsers?: MinimumUser[] | null;
|
||||||
channel?: Channel | null;
|
|
||||||
apMentions?: MinimumUser[] | null;
|
apMentions?: MinimumUser[] | null;
|
||||||
apHashtags?: string[] | null;
|
apHashtags?: string[] | null;
|
||||||
apEmojis?: string[] | null;
|
apEmojis?: string[] | null;
|
||||||
|
@ -176,39 +160,15 @@ export default async (
|
||||||
const dontFederateInitially =
|
const dontFederateInitially =
|
||||||
data.localOnly || data.visibility === "hidden";
|
data.localOnly || data.visibility === "hidden";
|
||||||
|
|
||||||
// If you reply outside the channel, match the scope of the target.
|
|
||||||
// TODO (I think it's a process that could be done on the client side, but it's server side for now.)
|
|
||||||
if (
|
|
||||||
data.reply &&
|
|
||||||
data.channel &&
|
|
||||||
data.reply.channelId !== data.channel.id
|
|
||||||
) {
|
|
||||||
if (data.reply.channelId) {
|
|
||||||
data.channel = await Channels.findOneBy({ id: data.reply.channelId });
|
|
||||||
} else {
|
|
||||||
data.channel = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// When you reply in a channel, match the scope of the target
|
|
||||||
// TODO (I think it's a process that could be done on the client side, but it's server side for now.)
|
|
||||||
if (data.reply && data.channel == null && data.reply.channelId) {
|
|
||||||
data.channel = await Channels.findOneBy({ id: data.reply.channelId });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.createdAt == null) data.createdAt = new Date();
|
if (data.createdAt == null) data.createdAt = new Date();
|
||||||
if (data.visibility == null) data.visibility = "public";
|
if (data.visibility == null) data.visibility = "public";
|
||||||
if (data.localOnly == null) data.localOnly = false;
|
if (data.localOnly == null) data.localOnly = false;
|
||||||
if (data.channel != null) data.visibility = "public";
|
|
||||||
if (data.channel != null) data.visibleUsers = [];
|
|
||||||
if (data.channel != null) data.localOnly = true;
|
|
||||||
if (data.visibility === "hidden") data.visibility = "public";
|
if (data.visibility === "hidden") data.visibility = "public";
|
||||||
|
|
||||||
// enforce silent clients on server
|
// enforce silent clients on server
|
||||||
if (
|
if (
|
||||||
user.isSilenced &&
|
user.isSilenced &&
|
||||||
data.visibility === "public" &&
|
data.visibility === "public"
|
||||||
data.channel == null
|
|
||||||
) {
|
) {
|
||||||
data.visibility = "home";
|
data.visibility = "home";
|
||||||
}
|
}
|
||||||
|
@ -256,12 +216,12 @@ export default async (
|
||||||
}
|
}
|
||||||
|
|
||||||
// Renote local only if you Renote local only.
|
// Renote local only if you Renote local only.
|
||||||
if (data.renote?.localOnly && data.channel == null) {
|
if (data.renote?.localOnly) {
|
||||||
data.localOnly = true;
|
data.localOnly = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If you reply to local only, make it local only.
|
// If you reply to local only, make it local only.
|
||||||
if (data.reply?.localOnly && data.channel == null) {
|
if (data.reply?.localOnly) {
|
||||||
data.localOnly = true;
|
data.localOnly = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,20 +346,6 @@ export default async (
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Channel
|
|
||||||
if (note.channelId) {
|
|
||||||
ChannelFollowings.findBy({ followeeId: note.channelId }).then(
|
|
||||||
(followings) => {
|
|
||||||
for (const following of followings) {
|
|
||||||
insertNoteUnread(following.followerId, note, {
|
|
||||||
isSpecified: false,
|
|
||||||
isMentioned: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.reply) {
|
if (data.reply) {
|
||||||
saveReply(data.reply, note);
|
saveReply(data.reply, note);
|
||||||
}
|
}
|
||||||
|
@ -644,24 +590,6 @@ export default async (
|
||||||
//#endregion
|
//#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.channel) {
|
|
||||||
Channels.increment({ id: data.channel.id }, "notesCount", 1);
|
|
||||||
Channels.update(data.channel.id, {
|
|
||||||
lastNotedAt: new Date(),
|
|
||||||
});
|
|
||||||
|
|
||||||
await Notes.countBy({
|
|
||||||
userId: user.id,
|
|
||||||
channelId: data.channel.id,
|
|
||||||
}).then((count) => {
|
|
||||||
// この処理が行われるのはノート作成後なので、ノートが一つしかなかったら最初の投稿だと判断できる
|
|
||||||
// TODO: とはいえノートを削除して何回も投稿すればその分だけインクリメントされる雑さもあるのでどうにかしたい
|
|
||||||
if (count === 1 && data.channel != null) {
|
|
||||||
Channels.increment({ id: data.channel.id }, "usersCount", 1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register to search database
|
// Register to search database
|
||||||
await index(note, false);
|
await index(note, false);
|
||||||
});
|
});
|
||||||
|
@ -712,7 +640,6 @@ async function insertNote(
|
||||||
fileIds: data.files ? data.files.map((file) => file.id) : [],
|
fileIds: data.files ? data.files.map((file) => file.id) : [],
|
||||||
replyId: data.reply ? data.reply.id : null,
|
replyId: data.reply ? data.reply.id : null,
|
||||||
renoteId: data.renote ? data.renote.id : null,
|
renoteId: data.renote ? data.renote.id : null,
|
||||||
channelId: data.channel ? data.channel.id : null,
|
|
||||||
threadId: data.reply
|
threadId: data.reply
|
||||||
? data.reply.threadId
|
? data.reply.threadId
|
||||||
? data.reply.threadId
|
? data.reply.threadId
|
||||||
|
@ -837,8 +764,7 @@ export async function index(note: Note, reindexing: boolean): Promise<void> {
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
id: note.id,
|
id: note.id,
|
||||||
userId: note.userId,
|
userId: note.userId,
|
||||||
userHost: note.userHost,
|
userHost: note.userHost
|
||||||
channelId: note.channelId,
|
|
||||||
}),
|
}),
|
||||||
note.text,
|
note.text,
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,19 +1,12 @@
|
||||||
import { publishMainStream } from "@/services/stream.js";
|
import {publishMainStream} from "@/services/stream.js";
|
||||||
import type { Note } from "@/models/entities/note.js";
|
import type {Note} from "@/models/entities/note.js";
|
||||||
import type { User } from "@/models/entities/user.js";
|
import type {User} from "@/models/entities/user.js";
|
||||||
import {
|
import {AntennaNotes, Followings, NoteUnreads, Users} from "@/models/index.js";
|
||||||
NoteUnreads,
|
import {In} from "typeorm";
|
||||||
AntennaNotes,
|
import {checkHitAntenna} from "@/misc/check-hit-antenna.js";
|
||||||
Users,
|
import {getAntennas} from "@/misc/antenna-cache.js";
|
||||||
Followings,
|
import {readNotificationByQuery} from "@/server/api/common/read-notification.js";
|
||||||
ChannelFollowings,
|
import type {Packed} from "@/misc/schema.js";
|
||||||
} from "@/models/index.js";
|
|
||||||
import { Not, IsNull, In } from "typeorm";
|
|
||||||
import type { Channel } from "@/models/entities/channel.js";
|
|
||||||
import { checkHitAntenna } from "@/misc/check-hit-antenna.js";
|
|
||||||
import { getAntennas } from "@/misc/antenna-cache.js";
|
|
||||||
import { readNotificationByQuery } from "@/server/api/common/read-notification.js";
|
|
||||||
import type { Packed } from "@/misc/schema.js";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mark notes as read
|
* Mark notes as read
|
||||||
|
@ -23,7 +16,6 @@ export default async function (
|
||||||
notes: (Note | Packed<"Note">)[],
|
notes: (Note | Packed<"Note">)[],
|
||||||
info?: {
|
info?: {
|
||||||
following: Set<User["id"]>;
|
following: Set<User["id"]>;
|
||||||
followingChannels: Set<Channel["id"]>;
|
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
const following = info?.following
|
const following = info?.following
|
||||||
|
@ -38,23 +30,10 @@ export default async function (
|
||||||
})
|
})
|
||||||
).map((x) => x.followeeId),
|
).map((x) => x.followeeId),
|
||||||
);
|
);
|
||||||
const followingChannels = info?.followingChannels
|
|
||||||
? info.followingChannels
|
|
||||||
: new Set<string>(
|
|
||||||
(
|
|
||||||
await ChannelFollowings.find({
|
|
||||||
where: {
|
|
||||||
followerId: userId,
|
|
||||||
},
|
|
||||||
select: ["followeeId"],
|
|
||||||
})
|
|
||||||
).map((x) => x.followeeId),
|
|
||||||
);
|
|
||||||
|
|
||||||
const myAntennas = (await getAntennas()).filter((a) => a.userId === userId);
|
const myAntennas = (await getAntennas()).filter((a) => a.userId === userId);
|
||||||
const readMentions: (Note | Packed<"Note">)[] = [];
|
const readMentions: (Note | Packed<"Note">)[] = [];
|
||||||
const readSpecifiedNotes: (Note | Packed<"Note">)[] = [];
|
const readSpecifiedNotes: (Note | Packed<"Note">)[] = [];
|
||||||
const readChannelNotes: (Note | Packed<"Note">)[] = [];
|
|
||||||
const readAntennaNotes: (Note | Packed<"Note">)[] = [];
|
const readAntennaNotes: (Note | Packed<"Note">)[] = [];
|
||||||
|
|
||||||
for (const note of notes) {
|
for (const note of notes) {
|
||||||
|
@ -64,10 +43,6 @@ export default async function (
|
||||||
readSpecifiedNotes.push(note);
|
readSpecifiedNotes.push(note);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (note.channelId && followingChannels.has(note.channelId)) {
|
|
||||||
readChannelNotes.push(note);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (note.user != null) {
|
if (note.user != null) {
|
||||||
// たぶんnullになることは無いはずだけど一応
|
// たぶんnullになることは無いはずだけど一応
|
||||||
for (const antenna of myAntennas) {
|
for (const antenna of myAntennas) {
|
||||||
|
@ -88,8 +63,7 @@ export default async function (
|
||||||
|
|
||||||
if (
|
if (
|
||||||
readMentions.length > 0 ||
|
readMentions.length > 0 ||
|
||||||
readSpecifiedNotes.length > 0 ||
|
readSpecifiedNotes.length > 0
|
||||||
readChannelNotes.length > 0
|
|
||||||
) {
|
) {
|
||||||
// Remove the record
|
// Remove the record
|
||||||
await NoteUnreads.delete({
|
await NoteUnreads.delete({
|
||||||
|
@ -97,7 +71,6 @@ export default async function (
|
||||||
noteId: In([
|
noteId: In([
|
||||||
...readMentions.map((n) => n.id),
|
...readMentions.map((n) => n.id),
|
||||||
...readSpecifiedNotes.map((n) => n.id),
|
...readSpecifiedNotes.map((n) => n.id),
|
||||||
...readChannelNotes.map((n) => n.id),
|
|
||||||
]),
|
]),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -123,16 +96,6 @@ export default async function (
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
NoteUnreads.countBy({
|
|
||||||
userId: userId,
|
|
||||||
noteChannelId: Not(IsNull()),
|
|
||||||
}).then((channelNoteCount) => {
|
|
||||||
if (channelNoteCount === 0) {
|
|
||||||
// 全て既読になったイベントを発行
|
|
||||||
publishMainStream(userId, "readAllChannels");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
readNotificationByQuery(userId, {
|
readNotificationByQuery(userId, {
|
||||||
noteId: In([
|
noteId: In([
|
||||||
...readMentions.map((n) => n.id),
|
...readMentions.map((n) => n.id),
|
||||||
|
|
|
@ -1,47 +1,23 @@
|
||||||
import { redisClient } from "../db/redis.js";
|
import {redisClient} from "../db/redis.js";
|
||||||
import type { User } from "@/models/entities/user.js";
|
import type {User} from "@/models/entities/user.js";
|
||||||
import type { Note } from "@/models/entities/note.js";
|
import type {Note} from "@/models/entities/note.js";
|
||||||
import type { UserList } from "@/models/entities/user-list.js";
|
import type {UserList} from "@/models/entities/user-list.js";
|
||||||
import type { UserGroup } from "@/models/entities/user-group.js";
|
|
||||||
import config from "@/config/index.js";
|
import config from "@/config/index.js";
|
||||||
import type { Antenna } from "@/models/entities/antenna.js";
|
import type {Antenna} from "@/models/entities/antenna.js";
|
||||||
import type { Channel } from "@/models/entities/channel.js";
|
|
||||||
import type {
|
import type {
|
||||||
StreamChannels,
|
|
||||||
AdminStreamTypes,
|
AdminStreamTypes,
|
||||||
AntennaStreamTypes,
|
AntennaStreamTypes,
|
||||||
BroadcastTypes,
|
BroadcastTypes,
|
||||||
ChannelStreamTypes,
|
|
||||||
DriveStreamTypes,
|
DriveStreamTypes,
|
||||||
InternalStreamTypes,
|
InternalStreamTypes,
|
||||||
MainStreamTypes,
|
MainStreamTypes,
|
||||||
NoteStreamTypes,
|
NoteStreamTypes,
|
||||||
|
StreamChannels,
|
||||||
UserListStreamTypes,
|
UserListStreamTypes,
|
||||||
UserStreamTypes,
|
UserStreamTypes,
|
||||||
} from "@/server/api/stream/types.js";
|
} from "@/server/api/stream/types.js";
|
||||||
|
|
||||||
class Publisher {
|
class Publisher {
|
||||||
private publish = (
|
|
||||||
channel: StreamChannels,
|
|
||||||
type: string | null,
|
|
||||||
value?: any,
|
|
||||||
): void => {
|
|
||||||
const message =
|
|
||||||
type == null
|
|
||||||
? value
|
|
||||||
: value == null
|
|
||||||
? { type: type, body: null }
|
|
||||||
: { type: type, body: value };
|
|
||||||
|
|
||||||
redisClient.publish(
|
|
||||||
config.host,
|
|
||||||
JSON.stringify({
|
|
||||||
channel: channel,
|
|
||||||
message: message,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
public publishInternalEvent = <K extends keyof InternalStreamTypes>(
|
public publishInternalEvent = <K extends keyof InternalStreamTypes>(
|
||||||
type: K,
|
type: K,
|
||||||
value?: InternalStreamTypes[K],
|
value?: InternalStreamTypes[K],
|
||||||
|
@ -107,18 +83,6 @@ class Publisher {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
public publishChannelStream = <K extends keyof ChannelStreamTypes>(
|
|
||||||
channelId: Channel["id"],
|
|
||||||
type: K,
|
|
||||||
value?: ChannelStreamTypes[K],
|
|
||||||
): void => {
|
|
||||||
this.publish(
|
|
||||||
`channelStream:${channelId}`,
|
|
||||||
type,
|
|
||||||
typeof value === "undefined" ? null : value,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
public publishUserListStream = <K extends keyof UserListStreamTypes>(
|
public publishUserListStream = <K extends keyof UserListStreamTypes>(
|
||||||
listId: UserList["id"],
|
listId: UserList["id"],
|
||||||
type: K,
|
type: K,
|
||||||
|
@ -158,6 +122,27 @@ class Publisher {
|
||||||
typeof value === "undefined" ? null : value,
|
typeof value === "undefined" ? null : value,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private publish = (
|
||||||
|
channel: StreamChannels,
|
||||||
|
type: string | null,
|
||||||
|
value?: any,
|
||||||
|
): void => {
|
||||||
|
const message =
|
||||||
|
type == null
|
||||||
|
? value
|
||||||
|
: value == null
|
||||||
|
? { type: type, body: null }
|
||||||
|
: { type: type, body: value };
|
||||||
|
|
||||||
|
redisClient.publish(
|
||||||
|
config.host,
|
||||||
|
JSON.stringify({
|
||||||
|
channel: channel,
|
||||||
|
message: message,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const publisher = new Publisher();
|
const publisher = new Publisher();
|
||||||
|
@ -171,7 +156,6 @@ export const publishMainStream = publisher.publishMainStream;
|
||||||
export const publishDriveStream = publisher.publishDriveStream;
|
export const publishDriveStream = publisher.publishDriveStream;
|
||||||
export const publishNoteStream = publisher.publishNoteStream;
|
export const publishNoteStream = publisher.publishNoteStream;
|
||||||
export const publishNotesStream = publisher.publishNotesStream;
|
export const publishNotesStream = publisher.publishNotesStream;
|
||||||
export const publishChannelStream = publisher.publishChannelStream;
|
|
||||||
export const publishUserListStream = publisher.publishUserListStream;
|
export const publishUserListStream = publisher.publishUserListStream;
|
||||||
export const publishAntennaStream = publisher.publishAntennaStream;
|
export const publishAntennaStream = publisher.publishAntennaStream;
|
||||||
export const publishAdminStream = publisher.publishAdminStream;
|
export const publishAdminStream = publisher.publishAdminStream;
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
root = true
|
|
||||||
|
|
||||||
[*]
|
|
||||||
indent_style = tab
|
|
||||||
indent_size = 2
|
|
||||||
charset = utf-8
|
|
||||||
insert_final_newline = true
|
|
|
@ -1,113 +0,0 @@
|
||||||
# Logs
|
|
||||||
logs
|
|
||||||
*.log
|
|
||||||
npm-debug.log*
|
|
||||||
yarn-debug.log*
|
|
||||||
yarn-error.log*
|
|
||||||
lerna-debug.log*
|
|
||||||
|
|
||||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
|
||||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
|
||||||
|
|
||||||
# Runtime data
|
|
||||||
pids
|
|
||||||
*.pid
|
|
||||||
*.seed
|
|
||||||
*.pid.lock
|
|
||||||
|
|
||||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
|
||||||
lib-cov
|
|
||||||
|
|
||||||
# Coverage directory used by tools like istanbul
|
|
||||||
coverage
|
|
||||||
*.lcov
|
|
||||||
|
|
||||||
# nyc test coverage
|
|
||||||
.nyc_output
|
|
||||||
|
|
||||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
|
||||||
.grunt
|
|
||||||
|
|
||||||
# Bower dependency directory (https://bower.io/)
|
|
||||||
bower_components
|
|
||||||
|
|
||||||
# node-waf configuration
|
|
||||||
.lock-wscript
|
|
||||||
|
|
||||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
|
||||||
build/Release
|
|
||||||
|
|
||||||
# Dependency directories
|
|
||||||
node_modules/
|
|
||||||
jspm_packages/
|
|
||||||
|
|
||||||
# TypeScript v1 declaration files
|
|
||||||
typings/
|
|
||||||
|
|
||||||
# TypeScript cache
|
|
||||||
*.tsbuildinfo
|
|
||||||
|
|
||||||
# Optional npm cache directory
|
|
||||||
.npm
|
|
||||||
|
|
||||||
# Optional eslint cache
|
|
||||||
.eslintcache
|
|
||||||
|
|
||||||
# Microbundle cache
|
|
||||||
.rpt2_cache/
|
|
||||||
.rts2_cache_cjs/
|
|
||||||
.rts2_cache_es/
|
|
||||||
.rts2_cache_umd/
|
|
||||||
|
|
||||||
# Optional REPL history
|
|
||||||
.node_repl_history
|
|
||||||
|
|
||||||
# Output of 'npm pack'
|
|
||||||
*.tgz
|
|
||||||
|
|
||||||
# Yarn Integrity file
|
|
||||||
.yarn-integrity
|
|
||||||
|
|
||||||
# dotenv environment variables file
|
|
||||||
.env
|
|
||||||
.env.test
|
|
||||||
|
|
||||||
# parcel-bundler cache (https://parceljs.org/)
|
|
||||||
.cache
|
|
||||||
|
|
||||||
# Next.js build output
|
|
||||||
.next
|
|
||||||
|
|
||||||
# Nuxt.js build / generate output
|
|
||||||
.nuxt
|
|
||||||
dist
|
|
||||||
|
|
||||||
# Gatsby files
|
|
||||||
.cache/
|
|
||||||
# Comment in the public line in if your project uses Gatsby and *not* Next.js
|
|
||||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
|
||||||
# public
|
|
||||||
|
|
||||||
# vuepress build output
|
|
||||||
.vuepress/dist
|
|
||||||
|
|
||||||
# Serverless directories
|
|
||||||
.serverless/
|
|
||||||
|
|
||||||
# FuseBox cache
|
|
||||||
.fusebox/
|
|
||||||
|
|
||||||
# DynamoDB Local files
|
|
||||||
.dynamodb/
|
|
||||||
|
|
||||||
# TernJS port file
|
|
||||||
.tern-port
|
|
||||||
|
|
||||||
# App
|
|
||||||
temp
|
|
||||||
# built
|
|
||||||
|
|
||||||
# Yarn
|
|
||||||
.yarn/*
|
|
||||||
.pnp.cjs
|
|
||||||
.pnp.loader.mjs
|
|
|
@ -1,20 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json.schemastore.org/swcrc",
|
|
||||||
"jsc": {
|
|
||||||
"parser": {
|
|
||||||
"syntax": "typescript",
|
|
||||||
"dynamicImport": true,
|
|
||||||
"decorators": true
|
|
||||||
},
|
|
||||||
"transform": {
|
|
||||||
"legacyDecorator": true,
|
|
||||||
"decoratorMetadata": true
|
|
||||||
},
|
|
||||||
"target": "es2022"
|
|
||||||
},
|
|
||||||
"minify": false,
|
|
||||||
"module": {
|
|
||||||
"type": "commonjs",
|
|
||||||
"strict": true
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
# 0.0.14
|
|
||||||
- remove needless Object.freeze()
|
|
||||||
|
|
||||||
# 0.0.13
|
|
||||||
- expose ChannelConnection and Channels types
|
|
||||||
|
|
||||||
# 0.0.12
|
|
||||||
- fix a bug that cannot connect to streaming
|
|
||||||
|
|
||||||
# 0.0.11
|
|
||||||
- update user type
|
|
||||||
- add missing main stream types
|
|
||||||
|
|
||||||
# 0.0.10
|
|
||||||
- add consts
|
|
||||||
|
|
||||||
# 0.0.9
|
|
||||||
- add list of api permission
|
|
||||||
- Update Note type
|
|
||||||
|
|
||||||
# 0.0.8
|
|
||||||
- add type definition for `messagingMessage` event to main stream channel
|
|
||||||
- Update Note type
|
|
||||||
|
|
||||||
# 0.0.7
|
|
||||||
- Notificationsの型を修正
|
|
||||||
- MessagingMessageの型を修正
|
|
||||||
- UserLiteの型を修正
|
|
||||||
- apiでネイティブfetchを格納する際に無名関数でラップするように
|
|
|
@ -1,21 +0,0 @@
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2021-2022 syuilo and other contributors
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
|
@ -1,9 +0,0 @@
|
||||||
# Calckey.js
|
|
||||||
|
|
||||||
Fork of Misskey.js for Calckey
|
|
||||||
|
|
||||||
https://www.npmjs.com/package/calckey-js
|
|
||||||
|
|
||||||
To fully build, run `pnpm i && pnpm run render`.
|
|
||||||
|
|
||||||
![Parody of the Javascript logo with "CK" instead of "JS"](https://codeberg.org/repo-avatars/80771-4d86135f67b9a460cdd1be9e91648e5f)
|
|
|
@ -1,364 +0,0 @@
|
||||||
/**
|
|
||||||
* Config file for API Extractor. For more info, please visit: https://api-extractor.com
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Optionally specifies another JSON config file that this file extends from. This provides a way for
|
|
||||||
* standard settings to be shared across multiple projects.
|
|
||||||
*
|
|
||||||
* If the path starts with "./" or "../", the path is resolved relative to the folder of the file that contains
|
|
||||||
* the "extends" field. Otherwise, the first path segment is interpreted as an NPM package name, and will be
|
|
||||||
* resolved using NodeJS require().
|
|
||||||
*
|
|
||||||
* SUPPORTED TOKENS: none
|
|
||||||
* DEFAULT VALUE: ""
|
|
||||||
*/
|
|
||||||
// "extends": "./shared/api-extractor-base.json"
|
|
||||||
// "extends": "my-package/include/api-extractor-base.json"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines the "<projectFolder>" token that can be used with other config file settings. The project folder
|
|
||||||
* typically contains the tsconfig.json and package.json config files, but the path is user-defined.
|
|
||||||
*
|
|
||||||
* The path is resolved relative to the folder of the config file that contains the setting.
|
|
||||||
*
|
|
||||||
* The default value for "projectFolder" is the token "<lookup>", which means the folder is determined by traversing
|
|
||||||
* parent folders, starting from the folder containing api-extractor.json, and stopping at the first folder
|
|
||||||
* that contains a tsconfig.json file. If a tsconfig.json file cannot be found in this way, then an error
|
|
||||||
* will be reported.
|
|
||||||
*
|
|
||||||
* SUPPORTED TOKENS: <lookup>
|
|
||||||
* DEFAULT VALUE: "<lookup>"
|
|
||||||
*/
|
|
||||||
// "projectFolder": "..",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (REQUIRED) Specifies the .d.ts file to be used as the starting point for analysis. API Extractor
|
|
||||||
* analyzes the symbols exported by this module.
|
|
||||||
*
|
|
||||||
* The file extension must be ".d.ts" and not ".ts".
|
|
||||||
*
|
|
||||||
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
|
|
||||||
* prepend a folder token such as "<projectFolder>".
|
|
||||||
*
|
|
||||||
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
|
|
||||||
*/
|
|
||||||
"mainEntryPointFilePath": "<projectFolder>/built/index.d.ts",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A list of NPM package names whose exports should be treated as part of this package.
|
|
||||||
*
|
|
||||||
* For example, suppose that Webpack is used to generate a distributed bundle for the project "library1",
|
|
||||||
* and another NPM package "library2" is embedded in this bundle. Some types from library2 may become part
|
|
||||||
* of the exported API for library1, but by default API Extractor would generate a .d.ts rollup that explicitly
|
|
||||||
* imports library2. To avoid this, we can specify:
|
|
||||||
*
|
|
||||||
* "bundledPackages": [ "library2" ],
|
|
||||||
*
|
|
||||||
* This would direct API Extractor to embed those types directly in the .d.ts rollup, as if they had been
|
|
||||||
* local files for library1.
|
|
||||||
*/
|
|
||||||
"bundledPackages": [],
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines how the TypeScript compiler engine will be invoked by API Extractor.
|
|
||||||
*/
|
|
||||||
"compiler": {
|
|
||||||
/**
|
|
||||||
* Specifies the path to the tsconfig.json file to be used by API Extractor when analyzing the project.
|
|
||||||
*
|
|
||||||
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
|
|
||||||
* prepend a folder token such as "<projectFolder>".
|
|
||||||
*
|
|
||||||
* Note: This setting will be ignored if "overrideTsconfig" is used.
|
|
||||||
*
|
|
||||||
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
|
|
||||||
* DEFAULT VALUE: "<projectFolder>/tsconfig.json"
|
|
||||||
*/
|
|
||||||
// "tsconfigFilePath": "<projectFolder>/tsconfig.json",
|
|
||||||
/**
|
|
||||||
* Provides a compiler configuration that will be used instead of reading the tsconfig.json file from disk.
|
|
||||||
* The object must conform to the TypeScript tsconfig schema:
|
|
||||||
*
|
|
||||||
* http://json.schemastore.org/tsconfig
|
|
||||||
*
|
|
||||||
* If omitted, then the tsconfig.json file will be read from the "projectFolder".
|
|
||||||
*
|
|
||||||
* DEFAULT VALUE: no overrideTsconfig section
|
|
||||||
*/
|
|
||||||
// "overrideTsconfig": {
|
|
||||||
// . . .
|
|
||||||
// }
|
|
||||||
/**
|
|
||||||
* This option causes the compiler to be invoked with the --skipLibCheck option. This option is not recommended
|
|
||||||
* and may cause API Extractor to produce incomplete or incorrect declarations, but it may be required when
|
|
||||||
* dependencies contain declarations that are incompatible with the TypeScript engine that API Extractor uses
|
|
||||||
* for its analysis. Where possible, the underlying issue should be fixed rather than relying on skipLibCheck.
|
|
||||||
*
|
|
||||||
* DEFAULT VALUE: false
|
|
||||||
*/
|
|
||||||
// "skipLibCheck": true,
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configures how the API report file (*.api.md) will be generated.
|
|
||||||
*/
|
|
||||||
"apiReport": {
|
|
||||||
/**
|
|
||||||
* (REQUIRED) Whether to generate an API report.
|
|
||||||
*/
|
|
||||||
"enabled": true
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The filename for the API report files. It will be combined with "reportFolder" or "reportTempFolder" to produce
|
|
||||||
* a full file path.
|
|
||||||
*
|
|
||||||
* The file extension should be ".api.md", and the string should not contain a path separator such as "\" or "/".
|
|
||||||
*
|
|
||||||
* SUPPORTED TOKENS: <packageName>, <unscopedPackageName>
|
|
||||||
* DEFAULT VALUE: "<unscopedPackageName>.api.md"
|
|
||||||
*/
|
|
||||||
// "reportFileName": "<unscopedPackageName>.api.md",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies the folder where the API report file is written. The file name portion is determined by
|
|
||||||
* the "reportFileName" setting.
|
|
||||||
*
|
|
||||||
* The API report file is normally tracked by Git. Changes to it can be used to trigger a branch policy,
|
|
||||||
* e.g. for an API review.
|
|
||||||
*
|
|
||||||
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
|
|
||||||
* prepend a folder token such as "<projectFolder>".
|
|
||||||
*
|
|
||||||
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
|
|
||||||
* DEFAULT VALUE: "<projectFolder>/etc/"
|
|
||||||
*/
|
|
||||||
// "reportFolder": "<projectFolder>/etc/",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies the folder where the temporary report file is written. The file name portion is determined by
|
|
||||||
* the "reportFileName" setting.
|
|
||||||
*
|
|
||||||
* After the temporary file is written to disk, it is compared with the file in the "reportFolder".
|
|
||||||
* If they are different, a production build will fail.
|
|
||||||
*
|
|
||||||
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
|
|
||||||
* prepend a folder token such as "<projectFolder>".
|
|
||||||
*
|
|
||||||
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
|
|
||||||
* DEFAULT VALUE: "<projectFolder>/temp/"
|
|
||||||
*/
|
|
||||||
// "reportTempFolder": "<projectFolder>/temp/"
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configures how the doc model file (*.api.json) will be generated.
|
|
||||||
*/
|
|
||||||
"docModel": {
|
|
||||||
/**
|
|
||||||
* (REQUIRED) Whether to generate a doc model file.
|
|
||||||
*/
|
|
||||||
"enabled": true
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The output path for the doc model file. The file extension should be ".api.json".
|
|
||||||
*
|
|
||||||
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
|
|
||||||
* prepend a folder token such as "<projectFolder>".
|
|
||||||
*
|
|
||||||
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
|
|
||||||
* DEFAULT VALUE: "<projectFolder>/temp/<unscopedPackageName>.api.json"
|
|
||||||
*/
|
|
||||||
// "apiJsonFilePath": "<projectFolder>/temp/<unscopedPackageName>.api.json"
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configures how the .d.ts rollup file will be generated.
|
|
||||||
*/
|
|
||||||
"dtsRollup": {
|
|
||||||
/**
|
|
||||||
* (REQUIRED) Whether to generate the .d.ts rollup file.
|
|
||||||
*/
|
|
||||||
"enabled": false
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies the output path for a .d.ts rollup file to be generated without any trimming.
|
|
||||||
* This file will include all declarations that are exported by the main entry point.
|
|
||||||
*
|
|
||||||
* If the path is an empty string, then this file will not be written.
|
|
||||||
*
|
|
||||||
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
|
|
||||||
* prepend a folder token such as "<projectFolder>".
|
|
||||||
*
|
|
||||||
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
|
|
||||||
* DEFAULT VALUE: "<projectFolder>/dist/<unscopedPackageName>.d.ts"
|
|
||||||
*/
|
|
||||||
// "untrimmedFilePath": "<projectFolder>/dist/<unscopedPackageName>.d.ts",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies the output path for a .d.ts rollup file to be generated with trimming for a "beta" release.
|
|
||||||
* This file will include only declarations that are marked as "@public" or "@beta".
|
|
||||||
*
|
|
||||||
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
|
|
||||||
* prepend a folder token such as "<projectFolder>".
|
|
||||||
*
|
|
||||||
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
|
|
||||||
* DEFAULT VALUE: ""
|
|
||||||
*/
|
|
||||||
// "betaTrimmedFilePath": "<projectFolder>/dist/<unscopedPackageName>-beta.d.ts",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies the output path for a .d.ts rollup file to be generated with trimming for a "public" release.
|
|
||||||
* This file will include only declarations that are marked as "@public".
|
|
||||||
*
|
|
||||||
* If the path is an empty string, then this file will not be written.
|
|
||||||
*
|
|
||||||
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
|
|
||||||
* prepend a folder token such as "<projectFolder>".
|
|
||||||
*
|
|
||||||
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
|
|
||||||
* DEFAULT VALUE: ""
|
|
||||||
*/
|
|
||||||
// "publicTrimmedFilePath": "<projectFolder>/dist/<unscopedPackageName>-public.d.ts",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When a declaration is trimmed, by default it will be replaced by a code comment such as
|
|
||||||
* "Excluded from this release type: exampleMember". Set "omitTrimmingComments" to true to remove the
|
|
||||||
* declaration completely.
|
|
||||||
*
|
|
||||||
* DEFAULT VALUE: false
|
|
||||||
*/
|
|
||||||
// "omitTrimmingComments": true
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configures how the tsdoc-metadata.json file will be generated.
|
|
||||||
*/
|
|
||||||
"tsdocMetadata": {
|
|
||||||
/**
|
|
||||||
* Whether to generate the tsdoc-metadata.json file.
|
|
||||||
*
|
|
||||||
* DEFAULT VALUE: true
|
|
||||||
*/
|
|
||||||
// "enabled": true,
|
|
||||||
/**
|
|
||||||
* Specifies where the TSDoc metadata file should be written.
|
|
||||||
*
|
|
||||||
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
|
|
||||||
* prepend a folder token such as "<projectFolder>".
|
|
||||||
*
|
|
||||||
* The default value is "<lookup>", which causes the path to be automatically inferred from the "tsdocMetadata",
|
|
||||||
* "typings" or "main" fields of the project's package.json. If none of these fields are set, the lookup
|
|
||||||
* falls back to "tsdoc-metadata.json" in the package folder.
|
|
||||||
*
|
|
||||||
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
|
|
||||||
* DEFAULT VALUE: "<lookup>"
|
|
||||||
*/
|
|
||||||
// "tsdocMetadataFilePath": "<projectFolder>/dist/tsdoc-metadata.json"
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies what type of newlines API Extractor should use when writing output files. By default, the output files
|
|
||||||
* will be written with Windows-style newlines. To use POSIX-style newlines, specify "lf" instead.
|
|
||||||
* To use the OS's default newline kind, specify "os".
|
|
||||||
*
|
|
||||||
* DEFAULT VALUE: "crlf"
|
|
||||||
*/
|
|
||||||
// "newlineKind": "crlf",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configures how API Extractor reports error and warning messages produced during analysis.
|
|
||||||
*
|
|
||||||
* There are three sources of messages: compiler messages, API Extractor messages, and TSDoc messages.
|
|
||||||
*/
|
|
||||||
"messages": {
|
|
||||||
/**
|
|
||||||
* Configures handling of diagnostic messages reported by the TypeScript compiler engine while analyzing
|
|
||||||
* the input .d.ts files.
|
|
||||||
*
|
|
||||||
* TypeScript message identifiers start with "TS" followed by an integer. For example: "TS2551"
|
|
||||||
*
|
|
||||||
* DEFAULT VALUE: A single "default" entry with logLevel=warning.
|
|
||||||
*/
|
|
||||||
"compilerMessageReporting": {
|
|
||||||
/**
|
|
||||||
* Configures the default routing for messages that don't match an explicit rule in this table.
|
|
||||||
*/
|
|
||||||
"default": {
|
|
||||||
/**
|
|
||||||
* Specifies whether the message should be written to the the tool's output log. Note that
|
|
||||||
* the "addToApiReportFile" property may supersede this option.
|
|
||||||
*
|
|
||||||
* Possible values: "error", "warning", "none"
|
|
||||||
*
|
|
||||||
* Errors cause the build to fail and return a nonzero exit code. Warnings cause a production build fail
|
|
||||||
* and return a nonzero exit code. For a non-production build (e.g. when "api-extractor run" includes
|
|
||||||
* the "--local" option), the warning is displayed but the build will not fail.
|
|
||||||
*
|
|
||||||
* DEFAULT VALUE: "warning"
|
|
||||||
*/
|
|
||||||
"logLevel": "warning"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When addToApiReportFile is true: If API Extractor is configured to write an API report file (.api.md),
|
|
||||||
* then the message will be written inside that file; otherwise, the message is instead logged according to
|
|
||||||
* the "logLevel" option.
|
|
||||||
*
|
|
||||||
* DEFAULT VALUE: false
|
|
||||||
*/
|
|
||||||
// "addToApiReportFile": false
|
|
||||||
}
|
|
||||||
|
|
||||||
// "TS2551": {
|
|
||||||
// "logLevel": "warning",
|
|
||||||
// "addToApiReportFile": true
|
|
||||||
// },
|
|
||||||
//
|
|
||||||
// . . .
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configures handling of messages reported by API Extractor during its analysis.
|
|
||||||
*
|
|
||||||
* API Extractor message identifiers start with "ae-". For example: "ae-extra-release-tag"
|
|
||||||
*
|
|
||||||
* DEFAULT VALUE: See api-extractor-defaults.json for the complete table of extractorMessageReporting mappings
|
|
||||||
*/
|
|
||||||
"extractorMessageReporting": {
|
|
||||||
"default": {
|
|
||||||
"logLevel": "none"
|
|
||||||
// "addToApiReportFile": false
|
|
||||||
}
|
|
||||||
|
|
||||||
// "ae-extra-release-tag": {
|
|
||||||
// "logLevel": "warning",
|
|
||||||
// "addToApiReportFile": true
|
|
||||||
// },
|
|
||||||
//
|
|
||||||
// . . .
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configures handling of messages reported by the TSDoc parser when analyzing code comments.
|
|
||||||
*
|
|
||||||
* TSDoc message identifiers start with "tsdoc-". For example: "tsdoc-link-tag-unescaped-text"
|
|
||||||
*
|
|
||||||
* DEFAULT VALUE: A single "default" entry with logLevel=warning.
|
|
||||||
*/
|
|
||||||
"tsdocMessageReporting": {
|
|
||||||
"default": {
|
|
||||||
"logLevel": "warning"
|
|
||||||
// "addToApiReportFile": false
|
|
||||||
}
|
|
||||||
|
|
||||||
// "tsdoc-link-tag-unescaped-text": {
|
|
||||||
// "logLevel": "warning",
|
|
||||||
// "addToApiReportFile": true
|
|
||||||
// },
|
|
||||||
//
|
|
||||||
// . . .
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
codecov:
|
|
||||||
token: d55e1270-f20a-4727-aa05-2bd57793315a
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,195 +0,0 @@
|
||||||
/*
|
|
||||||
* For a detailed explanation regarding each configuration property and type check, visit:
|
|
||||||
* https://jestjs.io/docs/en/configuration.html
|
|
||||||
*/
|
|
||||||
|
|
||||||
export default {
|
|
||||||
// All imported modules in your tests should be mocked automatically
|
|
||||||
// automock: false,
|
|
||||||
|
|
||||||
// Stop running tests after `n` failures
|
|
||||||
// bail: 0,
|
|
||||||
|
|
||||||
// The directory where Jest should store its cached dependency information
|
|
||||||
// cacheDirectory: "C:\\Users\\ai\\AppData\\Local\\Temp\\jest",
|
|
||||||
|
|
||||||
// Automatically clear mock calls and instances between every test
|
|
||||||
// clearMocks: false,
|
|
||||||
|
|
||||||
// Indicates whether the coverage information should be collected while executing the test
|
|
||||||
// collectCoverage: false,
|
|
||||||
|
|
||||||
// An array of glob patterns indicating a set of files for which coverage information should be collected
|
|
||||||
// collectCoverageFrom: undefined,
|
|
||||||
|
|
||||||
// The directory where Jest should output its coverage files
|
|
||||||
coverageDirectory: "coverage",
|
|
||||||
|
|
||||||
// An array of regexp pattern strings used to skip coverage collection
|
|
||||||
// coveragePathIgnorePatterns: [
|
|
||||||
// "\\\\node_modules\\\\"
|
|
||||||
// ],
|
|
||||||
|
|
||||||
// Indicates which provider should be used to instrument code for coverage
|
|
||||||
coverageProvider: "v8",
|
|
||||||
|
|
||||||
// A list of reporter names that Jest uses when writing coverage reports
|
|
||||||
// coverageReporters: [
|
|
||||||
// "json",
|
|
||||||
// "text",
|
|
||||||
// "lcov",
|
|
||||||
// "clover"
|
|
||||||
// ],
|
|
||||||
|
|
||||||
// An object that configures minimum threshold enforcement for coverage results
|
|
||||||
// coverageThreshold: undefined,
|
|
||||||
|
|
||||||
// A path to a custom dependency extractor
|
|
||||||
// dependencyExtractor: undefined,
|
|
||||||
|
|
||||||
// Make calling deprecated APIs throw helpful error messages
|
|
||||||
// errorOnDeprecated: false,
|
|
||||||
|
|
||||||
// Force coverage collection from ignored files using an array of glob patterns
|
|
||||||
// forceCoverageMatch: [],
|
|
||||||
|
|
||||||
// A path to a module which exports an async function that is triggered once before all test suites
|
|
||||||
// globalSetup: undefined,
|
|
||||||
|
|
||||||
// A path to a module which exports an async function that is triggered once after all test suites
|
|
||||||
// globalTeardown: undefined,
|
|
||||||
|
|
||||||
// A set of global variables that need to be available in all test environments
|
|
||||||
// globals: {},
|
|
||||||
|
|
||||||
// The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers.
|
|
||||||
// maxWorkers: "50%",
|
|
||||||
|
|
||||||
// An array of directory names to be searched recursively up from the requiring module's location
|
|
||||||
// moduleDirectories: [
|
|
||||||
// "node_modules"
|
|
||||||
// ],
|
|
||||||
|
|
||||||
// An array of file extensions your modules use
|
|
||||||
// moduleFileExtensions: [
|
|
||||||
// "js",
|
|
||||||
// "json",
|
|
||||||
// "jsx",
|
|
||||||
// "ts",
|
|
||||||
// "tsx",
|
|
||||||
// "node"
|
|
||||||
// ],
|
|
||||||
|
|
||||||
// A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module
|
|
||||||
// moduleNameMapper: {},
|
|
||||||
|
|
||||||
// An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader
|
|
||||||
// modulePathIgnorePatterns: [],
|
|
||||||
|
|
||||||
// Activates notifications for test results
|
|
||||||
// notify: false,
|
|
||||||
|
|
||||||
// An enum that specifies notification mode. Requires { notify: true }
|
|
||||||
// notifyMode: "failure-change",
|
|
||||||
|
|
||||||
// A preset that is used as a base for Jest's configuration
|
|
||||||
// preset: undefined,
|
|
||||||
|
|
||||||
// Run tests from one or more projects
|
|
||||||
// projects: undefined,
|
|
||||||
|
|
||||||
// Use this configuration option to add custom reporters to Jest
|
|
||||||
// reporters: undefined,
|
|
||||||
|
|
||||||
// Automatically reset mock state between every test
|
|
||||||
// resetMocks: false,
|
|
||||||
|
|
||||||
// Reset the module registry before running each individual test
|
|
||||||
// resetModules: false,
|
|
||||||
|
|
||||||
// A path to a custom resolver
|
|
||||||
// resolver: undefined,
|
|
||||||
|
|
||||||
// Automatically restore mock state between every test
|
|
||||||
// restoreMocks: false,
|
|
||||||
|
|
||||||
// The root directory that Jest should scan for tests and modules within
|
|
||||||
// rootDir: undefined,
|
|
||||||
|
|
||||||
// A list of paths to directories that Jest should use to search for files in
|
|
||||||
roots: ["<rootDir>"],
|
|
||||||
|
|
||||||
// Allows you to use a custom runner instead of Jest's default test runner
|
|
||||||
// runner: "jest-runner",
|
|
||||||
|
|
||||||
// The paths to modules that run some code to configure or set up the testing environment before each test
|
|
||||||
// setupFiles: [],
|
|
||||||
|
|
||||||
// A list of paths to modules that run some code to configure or set up the testing framework before each test
|
|
||||||
// setupFilesAfterEnv: [],
|
|
||||||
|
|
||||||
// The number of seconds after which a test is considered as slow and reported as such in the results.
|
|
||||||
// slowTestThreshold: 5,
|
|
||||||
|
|
||||||
// A list of paths to snapshot serializer modules Jest should use for snapshot testing
|
|
||||||
// snapshotSerializers: [],
|
|
||||||
|
|
||||||
// The test environment that will be used for testing
|
|
||||||
testEnvironment: "node",
|
|
||||||
|
|
||||||
// Options that will be passed to the testEnvironment
|
|
||||||
// testEnvironmentOptions: {},
|
|
||||||
|
|
||||||
// Adds a location field to test results
|
|
||||||
// testLocationInResults: false,
|
|
||||||
|
|
||||||
// The glob patterns Jest uses to detect test files
|
|
||||||
testMatch: [
|
|
||||||
"**/__tests__/**/*.[jt]s?(x)",
|
|
||||||
"**/?(*.)+(spec|test).[tj]s?(x)",
|
|
||||||
"<rootDir>/test/**/*",
|
|
||||||
],
|
|
||||||
|
|
||||||
// An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
|
|
||||||
// testPathIgnorePatterns: [
|
|
||||||
// "\\\\node_modules\\\\"
|
|
||||||
// ],
|
|
||||||
|
|
||||||
// The regexp pattern or array of patterns that Jest uses to detect test files
|
|
||||||
// testRegex: [],
|
|
||||||
|
|
||||||
// This option allows the use of a custom results processor
|
|
||||||
// testResultsProcessor: undefined,
|
|
||||||
|
|
||||||
// This option allows use of a custom test runner
|
|
||||||
// testRunner: "jasmine2",
|
|
||||||
|
|
||||||
// This option sets the URL for the jsdom environment. It is reflected in properties such as location.href
|
|
||||||
// testURL: "http://localhost",
|
|
||||||
|
|
||||||
// Setting this value to "fake" allows the use of fake timers for functions such as "setTimeout"
|
|
||||||
// timers: "real",
|
|
||||||
|
|
||||||
// A map from regular expressions to paths to transformers
|
|
||||||
transform: {
|
|
||||||
"^.+\\.(ts|tsx)$": "ts-jest",
|
|
||||||
},
|
|
||||||
|
|
||||||
// An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
|
|
||||||
// transformIgnorePatterns: [
|
|
||||||
// "\\\\node_modules\\\\",
|
|
||||||
// "\\.pnp\\.[^\\\\]+$"
|
|
||||||
// ],
|
|
||||||
|
|
||||||
// An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them
|
|
||||||
// unmockedModulePathPatterns: undefined,
|
|
||||||
|
|
||||||
// Indicates whether each individual test should be reported during the run
|
|
||||||
// verbose: undefined,
|
|
||||||
|
|
||||||
// An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode
|
|
||||||
// watchPathIgnorePatterns: [],
|
|
||||||
|
|
||||||
// Whether to use watchman for file crawling
|
|
||||||
// watchman: true,
|
|
||||||
};
|
|
|
@ -1,14 +0,0 @@
|
||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [calckey-js](./calckey-js.md) > [Acct](./calckey-js.acct.md)
|
|
||||||
|
|
||||||
## Acct type
|
|
||||||
|
|
||||||
**Signature:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
export declare type Acct = {
|
|
||||||
username: string;
|
|
||||||
host: string | null;
|
|
||||||
};
|
|
||||||
```
|
|
|
@ -1,24 +0,0 @@
|
||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [calckey-js](./calckey-js.md) > [api](./calckey-js.api.md) > [APIClient](./calckey-js.api.apiclient.md) > [(constructor)](./calckey-js.api.apiclient._constructor_.md)
|
|
||||||
|
|
||||||
## api.APIClient.(constructor)
|
|
||||||
|
|
||||||
Constructs a new instance of the `APIClient` class
|
|
||||||
|
|
||||||
**Signature:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
constructor(opts: {
|
|
||||||
origin: APIClient["origin"];
|
|
||||||
credential?: APIClient["credential"];
|
|
||||||
fetch?: APIClient["fetch"] | null | undefined;
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
## Parameters
|
|
||||||
|
|
||||||
| Parameter | Type | Description |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| opts | { origin: [APIClient](./calckey-js.api.apiclient.md)<!-- -->\["origin"\]; credential?: [APIClient](./calckey-js.api.apiclient.md)<!-- -->\["credential"\]; fetch?: [APIClient](./calckey-js.api.apiclient.md)<!-- -->\["fetch"\] \| null \| undefined; } | |
|
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [calckey-js](./calckey-js.md) > [api](./calckey-js.api.md) > [APIClient](./calckey-js.api.apiclient.md) > [credential](./calckey-js.api.apiclient.credential.md)
|
|
||||||
|
|
||||||
## api.APIClient.credential property
|
|
||||||
|
|
||||||
**Signature:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
credential: string | null | undefined;
|
|
||||||
```
|
|
|
@ -1,11 +0,0 @@
|
||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [calckey-js](./calckey-js.md) > [api](./calckey-js.api.md) > [APIClient](./calckey-js.api.apiclient.md) > [fetch](./calckey-js.api.apiclient.fetch.md)
|
|
||||||
|
|
||||||
## api.APIClient.fetch property
|
|
||||||
|
|
||||||
**Signature:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
fetch: FetchLike;
|
|
||||||
```
|
|
|
@ -1,32 +0,0 @@
|
||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [calckey-js](./calckey-js.md) > [api](./calckey-js.api.md) > [APIClient](./calckey-js.api.apiclient.md)
|
|
||||||
|
|
||||||
## api.APIClient class
|
|
||||||
|
|
||||||
**Signature:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
export declare class APIClient
|
|
||||||
```
|
|
||||||
|
|
||||||
## Constructors
|
|
||||||
|
|
||||||
| Constructor | Modifiers | Description |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| [(constructor)(opts)](./calckey-js.api.apiclient._constructor_.md) | | Constructs a new instance of the <code>APIClient</code> class |
|
|
||||||
|
|
||||||
## Properties
|
|
||||||
|
|
||||||
| Property | Modifiers | Type | Description |
|
|
||||||
| --- | --- | --- | --- |
|
|
||||||
| [credential](./calckey-js.api.apiclient.credential.md) | | string \| null \| undefined | |
|
|
||||||
| [fetch](./calckey-js.api.apiclient.fetch.md) | | [FetchLike](./calckey-js.api.fetchlike.md) | |
|
|
||||||
| [origin](./calckey-js.api.apiclient.origin.md) | | string | |
|
|
||||||
|
|
||||||
## Methods
|
|
||||||
|
|
||||||
| Method | Modifiers | Description |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| [request(endpoint, params, credential)](./calckey-js.api.apiclient.request.md) | | |
|
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [calckey-js](./calckey-js.md) > [api](./calckey-js.api.md) > [APIClient](./calckey-js.api.apiclient.md) > [origin](./calckey-js.api.apiclient.origin.md)
|
|
||||||
|
|
||||||
## api.APIClient.origin property
|
|
||||||
|
|
||||||
**Signature:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
origin: string;
|
|
||||||
```
|
|
|
@ -1,57 +0,0 @@
|
||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [calckey-js](./calckey-js.md) > [api](./calckey-js.api.md) > [APIClient](./calckey-js.api.apiclient.md) > [request](./calckey-js.api.apiclient.request.md)
|
|
||||||
|
|
||||||
## api.APIClient.request() method
|
|
||||||
|
|
||||||
**Signature:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
request<E extends keyof Endpoints, P extends Endpoints[E]["req"]>(
|
|
||||||
endpoint: E,
|
|
||||||
params?: P,
|
|
||||||
credential?: string | null | undefined,
|
|
||||||
): Promise<
|
|
||||||
Endpoints[E]["res"] extends {
|
|
||||||
$switch: {
|
|
||||||
$cases: [any, any][];
|
|
||||||
$default: any;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
? IsCaseMatched<E, P, 0> extends true
|
|
||||||
? GetCaseResult<E, P, 0>
|
|
||||||
: IsCaseMatched<E, P, 1> extends true
|
|
||||||
? GetCaseResult<E, P, 1>
|
|
||||||
: IsCaseMatched<E, P, 2> extends true
|
|
||||||
? GetCaseResult<E, P, 2>
|
|
||||||
: IsCaseMatched<E, P, 3> extends true
|
|
||||||
? GetCaseResult<E, P, 3>
|
|
||||||
: IsCaseMatched<E, P, 4> extends true
|
|
||||||
? GetCaseResult<E, P, 4>
|
|
||||||
: IsCaseMatched<E, P, 5> extends true
|
|
||||||
? GetCaseResult<E, P, 5>
|
|
||||||
: IsCaseMatched<E, P, 6> extends true
|
|
||||||
? GetCaseResult<E, P, 6>
|
|
||||||
: IsCaseMatched<E, P, 7> extends true
|
|
||||||
? GetCaseResult<E, P, 7>
|
|
||||||
: IsCaseMatched<E, P, 8> extends true
|
|
||||||
? GetCaseResult<E, P, 8>
|
|
||||||
: IsCaseMatched<E, P, 9> extends true
|
|
||||||
? GetCaseResult<E, P, 9>
|
|
||||||
: Endpoints[E]["res"]["$switch"]["$default"]
|
|
||||||
: Endpoints[E]["res"]
|
|
||||||
>;
|
|
||||||
```
|
|
||||||
|
|
||||||
## Parameters
|
|
||||||
|
|
||||||
| Parameter | Type | Description |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| endpoint | E | |
|
|
||||||
| params | P | _(Optional)_ |
|
|
||||||
| credential | string \| null \| undefined | _(Optional)_ |
|
|
||||||
|
|
||||||
**Returns:**
|
|
||||||
|
|
||||||
Promise< [Endpoints](./calckey-js.endpoints.md)<!-- -->\[E\]\["res"\] extends { $switch: { $cases: \[any, any\]\[\]; $default: any; }; } ? IsCaseMatched<E, P, 0> extends true ? GetCaseResult<E, P, 0> : IsCaseMatched<E, P, 1> extends true ? GetCaseResult<E, P, 1> : IsCaseMatched<E, P, 2> extends true ? GetCaseResult<E, P, 2> : IsCaseMatched<E, P, 3> extends true ? GetCaseResult<E, P, 3> : IsCaseMatched<E, P, 4> extends true ? GetCaseResult<E, P, 4> : IsCaseMatched<E, P, 5> extends true ? GetCaseResult<E, P, 5> : IsCaseMatched<E, P, 6> extends true ? GetCaseResult<E, P, 6> : IsCaseMatched<E, P, 7> extends true ? GetCaseResult<E, P, 7> : IsCaseMatched<E, P, 8> extends true ? GetCaseResult<E, P, 8> : IsCaseMatched<E, P, 9> extends true ? GetCaseResult<E, P, 9> : [Endpoints](./calckey-js.endpoints.md)<!-- -->\[E\]\["res"\]\["$switch"\]\["$default"\] : [Endpoints](./calckey-js.endpoints.md)<!-- -->\[E\]\["res"\] >
|
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [calckey-js](./calckey-js.md) > [api](./calckey-js.api.md) > [APIError](./calckey-js.api.apierror.md)
|
|
||||||
|
|
||||||
## api.APIError type
|
|
||||||
|
|
||||||
**Signature:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
export declare type APIError = {
|
|
||||||
id: string;
|
|
||||||
code: string;
|
|
||||||
message: string;
|
|
||||||
kind: "client" | "server";
|
|
||||||
info: Record<string, any>;
|
|
||||||
};
|
|
||||||
```
|
|
|
@ -1,22 +0,0 @@
|
||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [calckey-js](./calckey-js.md) > [api](./calckey-js.api.md) > [FetchLike](./calckey-js.api.fetchlike.md)
|
|
||||||
|
|
||||||
## api.FetchLike type
|
|
||||||
|
|
||||||
**Signature:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
export declare type FetchLike = (
|
|
||||||
input: string,
|
|
||||||
init?: {
|
|
||||||
method?: string;
|
|
||||||
body?: string;
|
|
||||||
credentials?: RequestCredentials;
|
|
||||||
cache?: RequestCache;
|
|
||||||
},
|
|
||||||
) => Promise<{
|
|
||||||
status: number;
|
|
||||||
json(): Promise<any>;
|
|
||||||
}>;
|
|
||||||
```
|
|
|
@ -1,22 +0,0 @@
|
||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [calckey-js](./calckey-js.md) > [api](./calckey-js.api.md) > [isAPIError](./calckey-js.api.isapierror.md)
|
|
||||||
|
|
||||||
## api.isAPIError() function
|
|
||||||
|
|
||||||
**Signature:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
export declare function isAPIError(reason: any): reason is APIError;
|
|
||||||
```
|
|
||||||
|
|
||||||
## Parameters
|
|
||||||
|
|
||||||
| Parameter | Type | Description |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| reason | any | |
|
|
||||||
|
|
||||||
**Returns:**
|
|
||||||
|
|
||||||
reason is [APIError](./calckey-js.api.apierror.md)
|
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [calckey-js](./calckey-js.md) > [api](./calckey-js.api.md)
|
|
||||||
|
|
||||||
## api namespace
|
|
||||||
|
|
||||||
## Classes
|
|
||||||
|
|
||||||
| Class | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| [APIClient](./calckey-js.api.apiclient.md) | |
|
|
||||||
|
|
||||||
## Functions
|
|
||||||
|
|
||||||
| Function | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| [isAPIError(reason)](./calckey-js.api.isapierror.md) | |
|
|
||||||
|
|
||||||
## Type Aliases
|
|
||||||
|
|
||||||
| Type Alias | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| [APIError](./calckey-js.api.apierror.md) | |
|
|
||||||
| [FetchLike](./calckey-js.api.fetchlike.md) | |
|
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [calckey-js](./calckey-js.md) > [ChannelConnection](./calckey-js.channelconnection.md) > [(constructor)](./calckey-js.channelconnection._constructor_.md)
|
|
||||||
|
|
||||||
## ChannelConnection.(constructor)
|
|
||||||
|
|
||||||
Constructs a new instance of the `Connection` class
|
|
||||||
|
|
||||||
**Signature:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
constructor(stream: Stream, channel: string, name?: string);
|
|
||||||
```
|
|
||||||
|
|
||||||
## Parameters
|
|
||||||
|
|
||||||
| Parameter | Type | Description |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| stream | [Stream](./calckey-js.stream.md) | |
|
|
||||||
| channel | string | |
|
|
||||||
| name | string | _(Optional)_ |
|
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [calckey-js](./calckey-js.md) > [ChannelConnection](./calckey-js.channelconnection.md) > [channel](./calckey-js.channelconnection.channel.md)
|
|
||||||
|
|
||||||
## ChannelConnection.channel property
|
|
||||||
|
|
||||||
**Signature:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
channel: string;
|
|
||||||
```
|
|
|
@ -1,15 +0,0 @@
|
||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [calckey-js](./calckey-js.md) > [ChannelConnection](./calckey-js.channelconnection.md) > [dispose](./calckey-js.channelconnection.dispose.md)
|
|
||||||
|
|
||||||
## ChannelConnection.dispose() method
|
|
||||||
|
|
||||||
**Signature:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
abstract dispose(): void;
|
|
||||||
```
|
|
||||||
**Returns:**
|
|
||||||
|
|
||||||
void
|
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [calckey-js](./calckey-js.md) > [ChannelConnection](./calckey-js.channelconnection.md) > [id](./calckey-js.channelconnection.id.md)
|
|
||||||
|
|
||||||
## ChannelConnection.id property
|
|
||||||
|
|
||||||
**Signature:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
abstract id: string;
|
|
||||||
```
|
|
|
@ -1,11 +0,0 @@
|
||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [calckey-js](./calckey-js.md) > [ChannelConnection](./calckey-js.channelconnection.md) > [inCount](./calckey-js.channelconnection.incount.md)
|
|
||||||
|
|
||||||
## ChannelConnection.inCount property
|
|
||||||
|
|
||||||
**Signature:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
inCount: number;
|
|
||||||
```
|
|
|
@ -1,39 +0,0 @@
|
||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [calckey-js](./calckey-js.md) > [ChannelConnection](./calckey-js.channelconnection.md)
|
|
||||||
|
|
||||||
## ChannelConnection class
|
|
||||||
|
|
||||||
**Signature:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
export declare abstract class Connection<
|
|
||||||
Channel extends AnyOf<Channels> = any,
|
|
||||||
> extends EventEmitter<Channel["events"]>
|
|
||||||
```
|
|
||||||
**Extends:** EventEmitter<Channel\["events"\]>
|
|
||||||
|
|
||||||
## Constructors
|
|
||||||
|
|
||||||
| Constructor | Modifiers | Description |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| [(constructor)(stream, channel, name)](./calckey-js.channelconnection._constructor_.md) | | Constructs a new instance of the <code>Connection</code> class |
|
|
||||||
|
|
||||||
## Properties
|
|
||||||
|
|
||||||
| Property | Modifiers | Type | Description |
|
|
||||||
| --- | --- | --- | --- |
|
|
||||||
| [channel](./calckey-js.channelconnection.channel.md) | | string | |
|
|
||||||
| [id](./calckey-js.channelconnection.id.md) | <code>abstract</code> | string | |
|
|
||||||
| [inCount](./calckey-js.channelconnection.incount.md) | | number | |
|
|
||||||
| [name?](./calckey-js.channelconnection.name.md) | | string | _(Optional)_ |
|
|
||||||
| [outCount](./calckey-js.channelconnection.outcount.md) | | number | |
|
|
||||||
| [stream](./calckey-js.channelconnection.stream.md) | <code>protected</code> | [Stream](./calckey-js.stream.md) | |
|
|
||||||
|
|
||||||
## Methods
|
|
||||||
|
|
||||||
| Method | Modifiers | Description |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| [dispose()](./calckey-js.channelconnection.dispose.md) | <code>abstract</code> | |
|
|
||||||
| [send(type, body)](./calckey-js.channelconnection.send.md) | | |
|
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [calckey-js](./calckey-js.md) > [ChannelConnection](./calckey-js.channelconnection.md) > [name](./calckey-js.channelconnection.name.md)
|
|
||||||
|
|
||||||
## ChannelConnection.name property
|
|
||||||
|
|
||||||
**Signature:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
name?: string;
|
|
||||||
```
|
|
|
@ -1,11 +0,0 @@
|
||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [calckey-js](./calckey-js.md) > [ChannelConnection](./calckey-js.channelconnection.md) > [outCount](./calckey-js.channelconnection.outcount.md)
|
|
||||||
|
|
||||||
## ChannelConnection.outCount property
|
|
||||||
|
|
||||||
**Signature:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
outCount: number;
|
|
||||||
```
|
|
|
@ -1,26 +0,0 @@
|
||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [calckey-js](./calckey-js.md) > [ChannelConnection](./calckey-js.channelconnection.md) > [send](./calckey-js.channelconnection.send.md)
|
|
||||||
|
|
||||||
## ChannelConnection.send() method
|
|
||||||
|
|
||||||
**Signature:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
send<T extends keyof Channel["receives"]>(
|
|
||||||
type: T,
|
|
||||||
body: Channel["receives"][T],
|
|
||||||
): void;
|
|
||||||
```
|
|
||||||
|
|
||||||
## Parameters
|
|
||||||
|
|
||||||
| Parameter | Type | Description |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| type | T | |
|
|
||||||
| body | Channel\["receives"\]\[T\] | |
|
|
||||||
|
|
||||||
**Returns:**
|
|
||||||
|
|
||||||
void
|
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [calckey-js](./calckey-js.md) > [ChannelConnection](./calckey-js.channelconnection.md) > [stream](./calckey-js.channelconnection.stream.md)
|
|
||||||
|
|
||||||
## ChannelConnection.stream property
|
|
||||||
|
|
||||||
**Signature:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
protected stream: Stream;
|
|
||||||
```
|
|
|
@ -1,143 +0,0 @@
|
||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [calckey-js](./calckey-js.md) > [Channels](./calckey-js.channels.md)
|
|
||||||
|
|
||||||
## Channels type
|
|
||||||
|
|
||||||
**Signature:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
export declare type Channels = {
|
|
||||||
main: {
|
|
||||||
params: null;
|
|
||||||
events: {
|
|
||||||
notification: (payload: Notification) => void;
|
|
||||||
mention: (payload: Note) => void;
|
|
||||||
reply: (payload: Note) => void;
|
|
||||||
renote: (payload: Note) => void;
|
|
||||||
follow: (payload: User) => void;
|
|
||||||
followed: (payload: User) => void;
|
|
||||||
unfollow: (payload: User) => void;
|
|
||||||
meUpdated: (payload: MeDetailed) => void;
|
|
||||||
pageEvent: (payload: PageEvent) => void;
|
|
||||||
urlUploadFinished: (payload: {
|
|
||||||
marker: string;
|
|
||||||
file: DriveFile;
|
|
||||||
}) => void;
|
|
||||||
readAllNotifications: () => void;
|
|
||||||
unreadNotification: (payload: Notification) => void;
|
|
||||||
unreadMention: (payload: Note["id"]) => void;
|
|
||||||
readAllUnreadMentions: () => void;
|
|
||||||
unreadSpecifiedNote: (payload: Note["id"]) => void;
|
|
||||||
readAllUnreadSpecifiedNotes: () => void;
|
|
||||||
readAllMessagingMessages: () => void;
|
|
||||||
messagingMessage: (payload: MessagingMessage) => void;
|
|
||||||
unreadMessagingMessage: (payload: MessagingMessage) => void;
|
|
||||||
readAllAntennas: () => void;
|
|
||||||
unreadAntenna: (payload: Antenna) => void;
|
|
||||||
readAllAnnouncements: () => void;
|
|
||||||
readAllChannels: () => void;
|
|
||||||
unreadChannel: (payload: Note["id"]) => void;
|
|
||||||
myTokenRegenerated: () => void;
|
|
||||||
reversiNoInvites: () => void;
|
|
||||||
reversiInvited: (payload: FIXME) => void;
|
|
||||||
signin: (payload: FIXME) => void;
|
|
||||||
registryUpdated: (payload: {
|
|
||||||
scope?: string[];
|
|
||||||
key: string;
|
|
||||||
value: any | null;
|
|
||||||
}) => void;
|
|
||||||
driveFileCreated: (payload: DriveFile) => void;
|
|
||||||
readAntenna: (payload: Antenna) => void;
|
|
||||||
};
|
|
||||||
receives: null;
|
|
||||||
};
|
|
||||||
homeTimeline: {
|
|
||||||
params: null;
|
|
||||||
events: {
|
|
||||||
note: (payload: Note) => void;
|
|
||||||
};
|
|
||||||
receives: null;
|
|
||||||
};
|
|
||||||
localTimeline: {
|
|
||||||
params: null;
|
|
||||||
events: {
|
|
||||||
note: (payload: Note) => void;
|
|
||||||
};
|
|
||||||
receives: null;
|
|
||||||
};
|
|
||||||
hybridTimeline: {
|
|
||||||
params: null;
|
|
||||||
events: {
|
|
||||||
note: (payload: Note) => void;
|
|
||||||
};
|
|
||||||
receives: null;
|
|
||||||
};
|
|
||||||
recommendedTimeline: {
|
|
||||||
params: null;
|
|
||||||
events: {
|
|
||||||
note: (payload: Note) => void;
|
|
||||||
};
|
|
||||||
receives: null;
|
|
||||||
};
|
|
||||||
globalTimeline: {
|
|
||||||
params: null;
|
|
||||||
events: {
|
|
||||||
note: (payload: Note) => void;
|
|
||||||
};
|
|
||||||
receives: null;
|
|
||||||
};
|
|
||||||
antenna: {
|
|
||||||
params: {
|
|
||||||
antennaId: Antenna["id"];
|
|
||||||
};
|
|
||||||
events: {
|
|
||||||
note: (payload: Note) => void;
|
|
||||||
};
|
|
||||||
receives: null;
|
|
||||||
};
|
|
||||||
messaging: {
|
|
||||||
params: {
|
|
||||||
otherparty?: User["id"] | null;
|
|
||||||
group?: UserGroup["id"] | null;
|
|
||||||
};
|
|
||||||
events: {
|
|
||||||
message: (payload: MessagingMessage) => void;
|
|
||||||
deleted: (payload: MessagingMessage["id"]) => void;
|
|
||||||
read: (payload: MessagingMessage["id"][]) => void;
|
|
||||||
typers: (payload: User[]) => void;
|
|
||||||
};
|
|
||||||
receives: {
|
|
||||||
read: {
|
|
||||||
id: MessagingMessage["id"];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
serverStats: {
|
|
||||||
params: null;
|
|
||||||
events: {
|
|
||||||
stats: (payload: FIXME) => void;
|
|
||||||
};
|
|
||||||
receives: {
|
|
||||||
requestLog: {
|
|
||||||
id: string | number;
|
|
||||||
length: number;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
queueStats: {
|
|
||||||
params: null;
|
|
||||||
events: {
|
|
||||||
stats: (payload: FIXME) => void;
|
|
||||||
};
|
|
||||||
receives: {
|
|
||||||
requestLog: {
|
|
||||||
id: string | number;
|
|
||||||
length: number;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
```
|
|
||||||
**References:** [Note](./calckey-js.entities.note.md)<!-- -->, [User](./calckey-js.entities.user.md)<!-- -->, [MeDetailed](./calckey-js.entities.medetailed.md)<!-- -->, [PageEvent](./calckey-js.entities.pageevent.md)<!-- -->, [DriveFile](./calckey-js.entities.drivefile.md)<!-- -->, [MessagingMessage](./calckey-js.entities.messagingmessage.md)<!-- -->, [Antenna](./calckey-js.entities.antenna.md)<!-- -->, [UserGroup](./calckey-js.entities.usergroup.md)
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,11 +0,0 @@
|
||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [calckey-js](./calckey-js.md) > [entities](./calckey-js.entities.md) > [Ad](./calckey-js.entities.ad.md)
|
|
||||||
|
|
||||||
## entities.Ad type
|
|
||||||
|
|
||||||
**Signature:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
export declare type Ad = TODO;
|
|
||||||
```
|
|
|
@ -1,21 +0,0 @@
|
||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [calckey-js](./calckey-js.md) > [entities](./calckey-js.entities.md) > [Announcement](./calckey-js.entities.announcement.md)
|
|
||||||
|
|
||||||
## entities.Announcement type
|
|
||||||
|
|
||||||
**Signature:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
export declare type Announcement = {
|
|
||||||
id: ID;
|
|
||||||
createdAt: DateString;
|
|
||||||
updatedAt: DateString | null;
|
|
||||||
text: string;
|
|
||||||
title: string;
|
|
||||||
imageUrl: string | null;
|
|
||||||
isRead?: boolean;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
**References:** [ID](./calckey-js.entities.id.md)<!-- -->, [DateString](./calckey-js.entities.datestring.md)
|
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [calckey-js](./calckey-js.md) > [entities](./calckey-js.entities.md) > [Antenna](./calckey-js.entities.antenna.md)
|
|
||||||
|
|
||||||
## entities.Antenna type
|
|
||||||
|
|
||||||
**Signature:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
export declare type Antenna = {
|
|
||||||
id: ID;
|
|
||||||
createdAt: DateString;
|
|
||||||
name: string;
|
|
||||||
keywords: string[][];
|
|
||||||
excludeKeywords: string[][];
|
|
||||||
src: "home" | "all" | "users" | "list" | "group" | "instances";
|
|
||||||
userListId: ID | null;
|
|
||||||
userGroupId: ID | null;
|
|
||||||
users: string[];
|
|
||||||
instances: string[];
|
|
||||||
caseSensitive: boolean;
|
|
||||||
notify: boolean;
|
|
||||||
withReplies: boolean;
|
|
||||||
withFile: boolean;
|
|
||||||
hasUnreadNote: boolean;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
**References:** [ID](./calckey-js.entities.id.md)<!-- -->, [DateString](./calckey-js.entities.datestring.md)
|
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [calckey-js](./calckey-js.md) > [entities](./calckey-js.entities.md) > [App](./calckey-js.entities.app.md)
|
|
||||||
|
|
||||||
## entities.App type
|
|
||||||
|
|
||||||
**Signature:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
export declare type App = TODO;
|
|
||||||
```
|
|
|
@ -1,17 +0,0 @@
|
||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [calckey-js](./calckey-js.md) > [entities](./calckey-js.entities.md) > [AuthSession](./calckey-js.entities.authsession.md)
|
|
||||||
|
|
||||||
## entities.AuthSession type
|
|
||||||
|
|
||||||
**Signature:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
export declare type AuthSession = {
|
|
||||||
id: ID;
|
|
||||||
app: App;
|
|
||||||
token: string;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
**References:** [ID](./calckey-js.entities.id.md)<!-- -->, [App](./calckey-js.entities.app.md)
|
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [calckey-js](./calckey-js.md) > [entities](./calckey-js.entities.md) > [Blocking](./calckey-js.entities.blocking.md)
|
|
||||||
|
|
||||||
## entities.Blocking type
|
|
||||||
|
|
||||||
**Signature:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
export declare type Blocking = {
|
|
||||||
id: ID;
|
|
||||||
createdAt: DateString;
|
|
||||||
blockeeId: User["id"];
|
|
||||||
blockee: UserDetailed;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
**References:** [ID](./calckey-js.entities.id.md)<!-- -->, [DateString](./calckey-js.entities.datestring.md)<!-- -->, [User](./calckey-js.entities.user.md)<!-- -->, [UserDetailed](./calckey-js.entities.userdetailed.md)
|
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [calckey-js](./calckey-js.md) > [entities](./calckey-js.entities.md) > [Channel](./calckey-js.entities.channel.md)
|
|
||||||
|
|
||||||
## entities.Channel type
|
|
||||||
|
|
||||||
**Signature:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
export declare type Channel = {
|
|
||||||
id: ID;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
**References:** [ID](./calckey-js.entities.id.md)
|
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [calckey-js](./calckey-js.md) > [entities](./calckey-js.entities.md) > [Clip](./calckey-js.entities.clip.md)
|
|
||||||
|
|
||||||
## entities.Clip type
|
|
||||||
|
|
||||||
**Signature:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
export declare type Clip = TODO;
|
|
||||||
```
|
|
|
@ -1,17 +0,0 @@
|
||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [calckey-js](./calckey-js.md) > [entities](./calckey-js.entities.md) > [CustomEmoji](./calckey-js.entities.customemoji.md)
|
|
||||||
|
|
||||||
## entities.CustomEmoji type
|
|
||||||
|
|
||||||
**Signature:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
export declare type CustomEmoji = {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
url: string;
|
|
||||||
category: string;
|
|
||||||
aliases: string[];
|
|
||||||
};
|
|
||||||
```
|
|
|
@ -1,11 +0,0 @@
|
||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [calckey-js](./calckey-js.md) > [entities](./calckey-js.entities.md) > [DateString](./calckey-js.entities.datestring.md)
|
|
||||||
|
|
||||||
## entities.DateString type
|
|
||||||
|
|
||||||
**Signature:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
export declare type DateString = string;
|
|
||||||
```
|
|
|
@ -1,15 +0,0 @@
|
||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [calckey-js](./calckey-js.md) > [entities](./calckey-js.entities.md) > [DetailedInstanceMetadata](./calckey-js.entities.detailedinstancemetadata.md)
|
|
||||||
|
|
||||||
## entities.DetailedInstanceMetadata type
|
|
||||||
|
|
||||||
**Signature:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
export declare type DetailedInstanceMetadata = LiteInstanceMetadata & {
|
|
||||||
features: Record<string, any>;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
**References:** [LiteInstanceMetadata](./calckey-js.entities.liteinstancemetadata.md)
|
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [calckey-js](./calckey-js.md) > [entities](./calckey-js.entities.md) > [DriveFile](./calckey-js.entities.drivefile.md)
|
|
||||||
|
|
||||||
## entities.DriveFile type
|
|
||||||
|
|
||||||
**Signature:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
export declare type DriveFile = {
|
|
||||||
id: ID;
|
|
||||||
createdAt: DateString;
|
|
||||||
isSensitive: boolean;
|
|
||||||
name: string;
|
|
||||||
thumbnailUrl: string;
|
|
||||||
url: string;
|
|
||||||
type: string;
|
|
||||||
size: number;
|
|
||||||
md5: string;
|
|
||||||
blurhash: string;
|
|
||||||
comment: string | null;
|
|
||||||
properties: Record<string, any>;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
**References:** [ID](./calckey-js.entities.id.md)<!-- -->, [DateString](./calckey-js.entities.datestring.md)
|
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [calckey-js](./calckey-js.md) > [entities](./calckey-js.entities.md) > [DriveFolder](./calckey-js.entities.drivefolder.md)
|
|
||||||
|
|
||||||
## entities.DriveFolder type
|
|
||||||
|
|
||||||
**Signature:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
export declare type DriveFolder = TODO;
|
|
||||||
```
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue