perf: remove charts (close #10611)
note: - ActiveUsersChart is kept - backend can be further refactored
This commit is contained in:
parent
fd0c8c5789
commit
a4603525aa
95 changed files with 1278 additions and 4510 deletions
|
@ -2,6 +2,21 @@
|
||||||
|
|
||||||
Breaking changes are indicated by the :warning: icon.
|
Breaking changes are indicated by the :warning: icon.
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
|
||||||
|
- :warning: The following endpoints are removed:
|
||||||
|
- `charts/ap-request`
|
||||||
|
- `charts/drive`
|
||||||
|
- `charts/federation`
|
||||||
|
- `charts/hashtag`
|
||||||
|
- `charts/instance`
|
||||||
|
- `charts/notes`
|
||||||
|
- `charts/user/drive`
|
||||||
|
- `charts/user/following`
|
||||||
|
- `charts/user/notes`
|
||||||
|
- `charts/user/reactions`
|
||||||
|
- `charts/users`
|
||||||
|
|
||||||
## v20240221
|
## v20240221
|
||||||
|
|
||||||
- Added `admin/set-emoji-moderator` endpoint, where moderators can give these permissions to regular users:
|
- Added `admin/set-emoji-moderator` endpoint, where moderators can give these permissions to regular users:
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
DELETE FROM "migrations" WHERE name IN (
|
DELETE FROM "migrations" WHERE name IN (
|
||||||
|
'RemoveCharts1709047957489',
|
||||||
'DropUserProfileLanguage1708452631156',
|
'DropUserProfileLanguage1708452631156',
|
||||||
'EmojiModerator1692825433698',
|
'EmojiModerator1692825433698',
|
||||||
'RemoveNsfwDetection1705848938166',
|
'RemoveNsfwDetection1705848938166',
|
||||||
|
@ -8,6 +9,584 @@ DELETE FROM "migrations" WHERE name IN (
|
||||||
'RemoveNativeUtilsMigration1705877093218'
|
'RemoveNativeUtilsMigration1705877093218'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
-- remove-charts
|
||||||
|
CREATE TABLE public.__chart__ap_request (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"___deliverFailed" integer DEFAULT 0 NOT NULL,
|
||||||
|
"___deliverSucceeded" integer DEFAULT 0 NOT NULL,
|
||||||
|
"___inboxReceived" integer DEFAULT 0 NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart__ap_request_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart__ap_request_id_seq OWNED BY public.__chart__ap_request.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart__drive (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"___local_incCount" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___local_incSize" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___local_decCount" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___local_decSize" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___remote_incCount" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___remote_incSize" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___remote_decCount" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___remote_decSize" integer DEFAULT '0'::bigint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart__drive_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart__drive_id_seq OWNED BY public.__chart__drive.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart__federation (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"unique_temp___deliveredInstances" character varying[] DEFAULT '{}'::character varying[] NOT NULL,
|
||||||
|
"___deliveredInstances" smallint DEFAULT '0'::smallint NOT NULL,
|
||||||
|
"unique_temp___inboxInstances" character varying[] DEFAULT '{}'::character varying[] NOT NULL,
|
||||||
|
"___inboxInstances" smallint DEFAULT '0'::smallint NOT NULL,
|
||||||
|
unique_temp___stalled character varying[] DEFAULT '{}'::character varying[] NOT NULL,
|
||||||
|
___stalled smallint DEFAULT '0'::smallint NOT NULL,
|
||||||
|
___sub smallint DEFAULT '0'::smallint NOT NULL,
|
||||||
|
___pub smallint DEFAULT '0'::smallint NOT NULL,
|
||||||
|
___pubsub smallint DEFAULT '0'::smallint NOT NULL,
|
||||||
|
"___subActive" smallint DEFAULT '0'::smallint NOT NULL,
|
||||||
|
"___pubActive" smallint DEFAULT '0'::smallint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart__federation_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart__federation_id_seq OWNED BY public.__chart__federation.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart__hashtag (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"group" character varying(128) NOT NULL,
|
||||||
|
___local_users integer DEFAULT 0 NOT NULL,
|
||||||
|
___remote_users integer DEFAULT 0 NOT NULL,
|
||||||
|
unique_temp___local_users character varying[] DEFAULT '{}'::character varying[] NOT NULL,
|
||||||
|
unique_temp___remote_users character varying[] DEFAULT '{}'::character varying[] NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart__hashtag_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart__hashtag_id_seq OWNED BY public.__chart__hashtag.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart__instance (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"group" character varying(128) NOT NULL,
|
||||||
|
___requests_failed smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___requests_succeeded smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___requests_received smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___notes_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___notes_inc integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___notes_dec integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___notes_diffs_normal integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___notes_diffs_reply integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___notes_diffs_renote integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___users_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___users_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___users_dec smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___following_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___following_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___following_dec smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___followers_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___followers_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___followers_dec smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___drive_totalFiles" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___drive_incFiles" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___drive_incUsage" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___drive_decFiles" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___drive_decUsage" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___notes_diffs_withFile" integer DEFAULT 0 NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart__instance_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart__instance_id_seq OWNED BY public.__chart__instance.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart__network (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"___incomingRequests" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___outgoingRequests" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___totalTime" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___incomingBytes" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___outgoingBytes" integer DEFAULT '0'::bigint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart__network_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart__network_id_seq OWNED BY public.__chart__network.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart__notes (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
___local_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_inc integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_dec integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_diffs_normal integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_diffs_reply integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_diffs_renote integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_inc integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_dec integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_diffs_normal integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_diffs_reply integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_diffs_renote integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___local_diffs_withFile" integer DEFAULT 0 NOT NULL,
|
||||||
|
"___remote_diffs_withFile" integer DEFAULT 0 NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart__notes_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart__notes_id_seq OWNED BY public.__chart__notes.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart__per_user_drive (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"group" character varying(128) NOT NULL,
|
||||||
|
"___totalCount" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___totalSize" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___incCount" smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___incSize" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___decCount" smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___decSize" integer DEFAULT '0'::bigint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart__per_user_drive_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart__per_user_drive_id_seq OWNED BY public.__chart__per_user_drive.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart__per_user_following (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"group" character varying(128) NOT NULL,
|
||||||
|
___local_followings_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_followings_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_followings_dec smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_followers_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_followers_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_followers_dec smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_followings_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_followings_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_followings_dec smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_followers_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_followers_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_followers_dec smallint DEFAULT '0'::bigint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart__per_user_following_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart__per_user_following_id_seq OWNED BY public.__chart__per_user_following.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart__per_user_notes (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"group" character varying(128) NOT NULL,
|
||||||
|
___total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___dec smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___diffs_normal smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___diffs_reply smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___diffs_renote smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___diffs_withFile" smallint DEFAULT '0'::smallint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart__per_user_notes_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart__per_user_notes_id_seq OWNED BY public.__chart__per_user_notes.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart__per_user_reaction (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"group" character varying(128) NOT NULL,
|
||||||
|
___local_count smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_count smallint DEFAULT '0'::bigint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart__per_user_reaction_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart__per_user_reaction_id_seq OWNED BY public.__chart__per_user_reaction.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart__test (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"group" character varying(128),
|
||||||
|
___foo_total bigint NOT NULL,
|
||||||
|
___foo_inc bigint NOT NULL,
|
||||||
|
___foo_dec bigint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE TABLE public.__chart__test_grouped (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"group" character varying(128),
|
||||||
|
___foo_total bigint NOT NULL,
|
||||||
|
___foo_inc bigint NOT NULL,
|
||||||
|
___foo_dec bigint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart__test_grouped_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart__test_grouped_id_seq OWNED BY public.__chart__test_grouped.id;
|
||||||
|
|
||||||
|
CREATE SEQUENCE public.__chart__test_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart__test_id_seq OWNED BY public.__chart__test.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart__test_unique (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"group" character varying(128),
|
||||||
|
___foo character varying[] DEFAULT '{}'::character varying[] NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart__test_unique_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart__test_unique_id_seq OWNED BY public.__chart__test_unique.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart__users (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
___local_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_dec smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_dec smallint DEFAULT '0'::bigint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart__users_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart__users_id_seq OWNED BY public.__chart__users.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart_day__ap_request (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"___deliverFailed" integer DEFAULT 0 NOT NULL,
|
||||||
|
"___deliverSucceeded" integer DEFAULT 0 NOT NULL,
|
||||||
|
"___inboxReceived" integer DEFAULT 0 NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart_day__ap_request_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart_day__ap_request_id_seq OWNED BY public.__chart_day__ap_request.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart_day__drive (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"___local_incCount" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___local_incSize" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___local_decCount" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___local_decSize" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___remote_incCount" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___remote_incSize" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___remote_decCount" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___remote_decSize" integer DEFAULT '0'::bigint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart_day__drive_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart_day__drive_id_seq OWNED BY public.__chart_day__drive.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart_day__federation (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"unique_temp___deliveredInstances" character varying[] DEFAULT '{}'::character varying[] NOT NULL,
|
||||||
|
"___deliveredInstances" smallint DEFAULT '0'::smallint NOT NULL,
|
||||||
|
"unique_temp___inboxInstances" character varying[] DEFAULT '{}'::character varying[] NOT NULL,
|
||||||
|
"___inboxInstances" smallint DEFAULT '0'::smallint NOT NULL,
|
||||||
|
unique_temp___stalled character varying[] DEFAULT '{}'::character varying[] NOT NULL,
|
||||||
|
___stalled smallint DEFAULT '0'::smallint NOT NULL,
|
||||||
|
___sub smallint DEFAULT '0'::smallint NOT NULL,
|
||||||
|
___pub smallint DEFAULT '0'::smallint NOT NULL,
|
||||||
|
___pubsub smallint DEFAULT '0'::smallint NOT NULL,
|
||||||
|
"___subActive" smallint DEFAULT '0'::smallint NOT NULL,
|
||||||
|
"___pubActive" smallint DEFAULT '0'::smallint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart_day__federation_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart_day__federation_id_seq OWNED BY public.__chart_day__federation.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart_day__hashtag (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"group" character varying(128) NOT NULL,
|
||||||
|
___local_users integer DEFAULT 0 NOT NULL,
|
||||||
|
___remote_users integer DEFAULT 0 NOT NULL,
|
||||||
|
unique_temp___local_users character varying[] DEFAULT '{}'::character varying[] NOT NULL,
|
||||||
|
unique_temp___remote_users character varying[] DEFAULT '{}'::character varying[] NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart_day__hashtag_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart_day__hashtag_id_seq OWNED BY public.__chart_day__hashtag.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart_day__instance (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"group" character varying(128) NOT NULL,
|
||||||
|
___requests_failed smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___requests_succeeded smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___requests_received smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___notes_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___notes_inc integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___notes_dec integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___notes_diffs_normal integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___notes_diffs_reply integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___notes_diffs_renote integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___users_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___users_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___users_dec smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___following_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___following_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___following_dec smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___followers_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___followers_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___followers_dec smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___drive_totalFiles" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___drive_incFiles" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___drive_incUsage" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___drive_decFiles" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___drive_decUsage" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___notes_diffs_withFile" integer DEFAULT 0 NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart_day__instance_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart_day__instance_id_seq OWNED BY public.__chart_day__instance.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart_day__network (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"___incomingRequests" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___outgoingRequests" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___totalTime" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___incomingBytes" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___outgoingBytes" integer DEFAULT '0'::bigint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart_day__network_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart_day__network_id_seq OWNED BY public.__chart_day__network.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart_day__notes (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
___local_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_inc integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_dec integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_diffs_normal integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_diffs_reply integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_diffs_renote integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_inc integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_dec integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_diffs_normal integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_diffs_reply integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_diffs_renote integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___local_diffs_withFile" integer DEFAULT 0 NOT NULL,
|
||||||
|
"___remote_diffs_withFile" integer DEFAULT 0 NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart_day__notes_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart_day__notes_id_seq OWNED BY public.__chart_day__notes.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart_day__per_user_drive (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"group" character varying(128) NOT NULL,
|
||||||
|
"___totalCount" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___totalSize" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___incCount" smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___incSize" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___decCount" smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___decSize" integer DEFAULT '0'::bigint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart_day__per_user_drive_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart_day__per_user_drive_id_seq OWNED BY public.__chart_day__per_user_drive.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart_day__per_user_following (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"group" character varying(128) NOT NULL,
|
||||||
|
___local_followings_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_followings_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_followings_dec smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_followers_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_followers_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_followers_dec smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_followings_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_followings_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_followings_dec smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_followers_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_followers_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_followers_dec smallint DEFAULT '0'::bigint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart_day__per_user_following_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart_day__per_user_following_id_seq OWNED BY public.__chart_day__per_user_following.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart_day__per_user_notes (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"group" character varying(128) NOT NULL,
|
||||||
|
___total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___dec smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___diffs_normal smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___diffs_reply smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___diffs_renote smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___diffs_withFile" smallint DEFAULT '0'::smallint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart_day__per_user_notes_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart_day__per_user_notes_id_seq OWNED BY public.__chart_day__per_user_notes.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart_day__per_user_reaction (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"group" character varying(128) NOT NULL,
|
||||||
|
___local_count smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_count smallint DEFAULT '0'::bigint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart_day__per_user_reaction_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart_day__per_user_reaction_id_seq OWNED BY public.__chart_day__per_user_reaction.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart_day__users (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
___local_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_dec smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_dec smallint DEFAULT '0'::bigint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart_day__users_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart_day__users_id_seq OWNED BY public.__chart_day__users.id;
|
||||||
|
|
||||||
-- drop-user-profile-language
|
-- drop-user-profile-language
|
||||||
ALTER TABLE "user_profile" ADD COLUMN "lang" character varying(32);
|
ALTER TABLE "user_profile" ADD COLUMN "lang" character varying(32);
|
||||||
|
|
||||||
|
|
618
packages/backend/migration/1709047957489-remove-charts.js
Normal file
618
packages/backend/migration/1709047957489-remove-charts.js
Normal file
|
@ -0,0 +1,618 @@
|
||||||
|
export class RemoveCharts1709047957489 {
|
||||||
|
name = "RemoveCharts1709047957489";
|
||||||
|
|
||||||
|
async up(queryRunner) {
|
||||||
|
await queryRunner.query(`DROP TABLE "__chart__ap_request" CASCADE`);
|
||||||
|
await queryRunner.query(`DROP TABLE "__chart_day__ap_request" CASCADE`);
|
||||||
|
await queryRunner.query(`DROP TABLE "__chart_day__drive" CASCADE`);
|
||||||
|
await queryRunner.query(`DROP TABLE "__chart_day__federation" CASCADE`);
|
||||||
|
await queryRunner.query(`DROP TABLE "__chart_day__hashtag" CASCADE`);
|
||||||
|
await queryRunner.query(`DROP TABLE "__chart_day__instance" CASCADE`);
|
||||||
|
await queryRunner.query(`DROP TABLE "__chart_day__network" CASCADE`);
|
||||||
|
await queryRunner.query(`DROP TABLE "__chart_day__notes" CASCADE`);
|
||||||
|
await queryRunner.query(`DROP TABLE "__chart_day__per_user_drive" CASCADE`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`DROP TABLE "__chart_day__per_user_following" CASCADE`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(`DROP TABLE "__chart_day__per_user_notes" CASCADE`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`DROP TABLE "__chart_day__per_user_reaction" CASCADE`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(`DROP TABLE "__chart_day__users" CASCADE`);
|
||||||
|
await queryRunner.query(`DROP TABLE "__chart__drive" CASCADE`);
|
||||||
|
await queryRunner.query(`DROP TABLE "__chart__federation" CASCADE`);
|
||||||
|
await queryRunner.query(`DROP TABLE "__chart__hashtag" CASCADE`);
|
||||||
|
await queryRunner.query(`DROP TABLE "__chart__instance" CASCADE`);
|
||||||
|
await queryRunner.query(`DROP TABLE "__chart__network" CASCADE`);
|
||||||
|
await queryRunner.query(`DROP TABLE "__chart__notes" CASCADE`);
|
||||||
|
await queryRunner.query(`DROP TABLE "__chart__per_user_drive" CASCADE`);
|
||||||
|
await queryRunner.query(`DROP TABLE "__chart__per_user_following" CASCADE`);
|
||||||
|
await queryRunner.query(`DROP TABLE "__chart__per_user_notes" CASCADE`);
|
||||||
|
await queryRunner.query(`DROP TABLE "__chart__per_user_reaction" CASCADE`);
|
||||||
|
await queryRunner.query(`DROP TABLE "__chart__test" CASCADE`);
|
||||||
|
await queryRunner.query(`DROP TABLE "__chart__test_unique" CASCADE`);
|
||||||
|
await queryRunner.query(`DROP TABLE "__chart__test_grouped" CASCADE`);
|
||||||
|
await queryRunner.query(`DROP TABLE "__chart__users" CASCADE`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async down(queryRunner) {
|
||||||
|
await queryRunner.query(`
|
||||||
|
CREATE TABLE public.__chart__ap_request (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"___deliverFailed" integer DEFAULT 0 NOT NULL,
|
||||||
|
"___deliverSucceeded" integer DEFAULT 0 NOT NULL,
|
||||||
|
"___inboxReceived" integer DEFAULT 0 NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart__ap_request_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart__ap_request_id_seq OWNED BY public.__chart__ap_request.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart__drive (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"___local_incCount" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___local_incSize" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___local_decCount" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___local_decSize" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___remote_incCount" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___remote_incSize" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___remote_decCount" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___remote_decSize" integer DEFAULT '0'::bigint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart__drive_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart__drive_id_seq OWNED BY public.__chart__drive.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart__federation (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"unique_temp___deliveredInstances" character varying[] DEFAULT '{}'::character varying[] NOT NULL,
|
||||||
|
"___deliveredInstances" smallint DEFAULT '0'::smallint NOT NULL,
|
||||||
|
"unique_temp___inboxInstances" character varying[] DEFAULT '{}'::character varying[] NOT NULL,
|
||||||
|
"___inboxInstances" smallint DEFAULT '0'::smallint NOT NULL,
|
||||||
|
unique_temp___stalled character varying[] DEFAULT '{}'::character varying[] NOT NULL,
|
||||||
|
___stalled smallint DEFAULT '0'::smallint NOT NULL,
|
||||||
|
___sub smallint DEFAULT '0'::smallint NOT NULL,
|
||||||
|
___pub smallint DEFAULT '0'::smallint NOT NULL,
|
||||||
|
___pubsub smallint DEFAULT '0'::smallint NOT NULL,
|
||||||
|
"___subActive" smallint DEFAULT '0'::smallint NOT NULL,
|
||||||
|
"___pubActive" smallint DEFAULT '0'::smallint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart__federation_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart__federation_id_seq OWNED BY public.__chart__federation.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart__hashtag (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"group" character varying(128) NOT NULL,
|
||||||
|
___local_users integer DEFAULT 0 NOT NULL,
|
||||||
|
___remote_users integer DEFAULT 0 NOT NULL,
|
||||||
|
unique_temp___local_users character varying[] DEFAULT '{}'::character varying[] NOT NULL,
|
||||||
|
unique_temp___remote_users character varying[] DEFAULT '{}'::character varying[] NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart__hashtag_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart__hashtag_id_seq OWNED BY public.__chart__hashtag.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart__instance (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"group" character varying(128) NOT NULL,
|
||||||
|
___requests_failed smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___requests_succeeded smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___requests_received smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___notes_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___notes_inc integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___notes_dec integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___notes_diffs_normal integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___notes_diffs_reply integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___notes_diffs_renote integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___users_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___users_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___users_dec smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___following_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___following_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___following_dec smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___followers_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___followers_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___followers_dec smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___drive_totalFiles" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___drive_incFiles" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___drive_incUsage" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___drive_decFiles" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___drive_decUsage" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___notes_diffs_withFile" integer DEFAULT 0 NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart__instance_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart__instance_id_seq OWNED BY public.__chart__instance.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart__network (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"___incomingRequests" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___outgoingRequests" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___totalTime" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___incomingBytes" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___outgoingBytes" integer DEFAULT '0'::bigint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart__network_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart__network_id_seq OWNED BY public.__chart__network.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart__notes (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
___local_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_inc integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_dec integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_diffs_normal integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_diffs_reply integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_diffs_renote integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_inc integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_dec integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_diffs_normal integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_diffs_reply integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_diffs_renote integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___local_diffs_withFile" integer DEFAULT 0 NOT NULL,
|
||||||
|
"___remote_diffs_withFile" integer DEFAULT 0 NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart__notes_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart__notes_id_seq OWNED BY public.__chart__notes.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart__per_user_drive (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"group" character varying(128) NOT NULL,
|
||||||
|
"___totalCount" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___totalSize" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___incCount" smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___incSize" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___decCount" smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___decSize" integer DEFAULT '0'::bigint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart__per_user_drive_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart__per_user_drive_id_seq OWNED BY public.__chart__per_user_drive.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart__per_user_following (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"group" character varying(128) NOT NULL,
|
||||||
|
___local_followings_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_followings_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_followings_dec smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_followers_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_followers_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_followers_dec smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_followings_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_followings_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_followings_dec smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_followers_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_followers_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_followers_dec smallint DEFAULT '0'::bigint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart__per_user_following_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart__per_user_following_id_seq OWNED BY public.__chart__per_user_following.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart__per_user_notes (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"group" character varying(128) NOT NULL,
|
||||||
|
___total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___dec smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___diffs_normal smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___diffs_reply smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___diffs_renote smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___diffs_withFile" smallint DEFAULT '0'::smallint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart__per_user_notes_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart__per_user_notes_id_seq OWNED BY public.__chart__per_user_notes.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart__per_user_reaction (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"group" character varying(128) NOT NULL,
|
||||||
|
___local_count smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_count smallint DEFAULT '0'::bigint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart__per_user_reaction_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart__per_user_reaction_id_seq OWNED BY public.__chart__per_user_reaction.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart__test (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"group" character varying(128),
|
||||||
|
___foo_total bigint NOT NULL,
|
||||||
|
___foo_inc bigint NOT NULL,
|
||||||
|
___foo_dec bigint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE TABLE public.__chart__test_grouped (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"group" character varying(128),
|
||||||
|
___foo_total bigint NOT NULL,
|
||||||
|
___foo_inc bigint NOT NULL,
|
||||||
|
___foo_dec bigint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart__test_grouped_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart__test_grouped_id_seq OWNED BY public.__chart__test_grouped.id;
|
||||||
|
|
||||||
|
CREATE SEQUENCE public.__chart__test_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart__test_id_seq OWNED BY public.__chart__test.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart__test_unique (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"group" character varying(128),
|
||||||
|
___foo character varying[] DEFAULT '{}'::character varying[] NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart__test_unique_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart__test_unique_id_seq OWNED BY public.__chart__test_unique.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart__users (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
___local_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_dec smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_dec smallint DEFAULT '0'::bigint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart__users_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart__users_id_seq OWNED BY public.__chart__users.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart_day__ap_request (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"___deliverFailed" integer DEFAULT 0 NOT NULL,
|
||||||
|
"___deliverSucceeded" integer DEFAULT 0 NOT NULL,
|
||||||
|
"___inboxReceived" integer DEFAULT 0 NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart_day__ap_request_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart_day__ap_request_id_seq OWNED BY public.__chart_day__ap_request.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart_day__drive (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"___local_incCount" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___local_incSize" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___local_decCount" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___local_decSize" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___remote_incCount" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___remote_incSize" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___remote_decCount" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___remote_decSize" integer DEFAULT '0'::bigint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart_day__drive_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart_day__drive_id_seq OWNED BY public.__chart_day__drive.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart_day__federation (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"unique_temp___deliveredInstances" character varying[] DEFAULT '{}'::character varying[] NOT NULL,
|
||||||
|
"___deliveredInstances" smallint DEFAULT '0'::smallint NOT NULL,
|
||||||
|
"unique_temp___inboxInstances" character varying[] DEFAULT '{}'::character varying[] NOT NULL,
|
||||||
|
"___inboxInstances" smallint DEFAULT '0'::smallint NOT NULL,
|
||||||
|
unique_temp___stalled character varying[] DEFAULT '{}'::character varying[] NOT NULL,
|
||||||
|
___stalled smallint DEFAULT '0'::smallint NOT NULL,
|
||||||
|
___sub smallint DEFAULT '0'::smallint NOT NULL,
|
||||||
|
___pub smallint DEFAULT '0'::smallint NOT NULL,
|
||||||
|
___pubsub smallint DEFAULT '0'::smallint NOT NULL,
|
||||||
|
"___subActive" smallint DEFAULT '0'::smallint NOT NULL,
|
||||||
|
"___pubActive" smallint DEFAULT '0'::smallint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart_day__federation_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart_day__federation_id_seq OWNED BY public.__chart_day__federation.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart_day__hashtag (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"group" character varying(128) NOT NULL,
|
||||||
|
___local_users integer DEFAULT 0 NOT NULL,
|
||||||
|
___remote_users integer DEFAULT 0 NOT NULL,
|
||||||
|
unique_temp___local_users character varying[] DEFAULT '{}'::character varying[] NOT NULL,
|
||||||
|
unique_temp___remote_users character varying[] DEFAULT '{}'::character varying[] NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart_day__hashtag_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart_day__hashtag_id_seq OWNED BY public.__chart_day__hashtag.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart_day__instance (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"group" character varying(128) NOT NULL,
|
||||||
|
___requests_failed smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___requests_succeeded smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___requests_received smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___notes_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___notes_inc integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___notes_dec integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___notes_diffs_normal integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___notes_diffs_reply integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___notes_diffs_renote integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___users_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___users_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___users_dec smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___following_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___following_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___following_dec smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___followers_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___followers_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___followers_dec smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___drive_totalFiles" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___drive_incFiles" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___drive_incUsage" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___drive_decFiles" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___drive_decUsage" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___notes_diffs_withFile" integer DEFAULT 0 NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart_day__instance_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart_day__instance_id_seq OWNED BY public.__chart_day__instance.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart_day__network (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"___incomingRequests" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___outgoingRequests" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___totalTime" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___incomingBytes" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___outgoingBytes" integer DEFAULT '0'::bigint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart_day__network_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart_day__network_id_seq OWNED BY public.__chart_day__network.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart_day__notes (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
___local_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_inc integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_dec integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_diffs_normal integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_diffs_reply integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_diffs_renote integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_inc integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_dec integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_diffs_normal integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_diffs_reply integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_diffs_renote integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___local_diffs_withFile" integer DEFAULT 0 NOT NULL,
|
||||||
|
"___remote_diffs_withFile" integer DEFAULT 0 NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart_day__notes_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart_day__notes_id_seq OWNED BY public.__chart_day__notes.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart_day__per_user_drive (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"group" character varying(128) NOT NULL,
|
||||||
|
"___totalCount" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___totalSize" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___incCount" smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___incSize" integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___decCount" smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___decSize" integer DEFAULT '0'::bigint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart_day__per_user_drive_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart_day__per_user_drive_id_seq OWNED BY public.__chart_day__per_user_drive.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart_day__per_user_following (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"group" character varying(128) NOT NULL,
|
||||||
|
___local_followings_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_followings_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_followings_dec smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_followers_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_followers_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_followers_dec smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_followings_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_followings_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_followings_dec smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_followers_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_followers_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_followers_dec smallint DEFAULT '0'::bigint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart_day__per_user_following_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart_day__per_user_following_id_seq OWNED BY public.__chart_day__per_user_following.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart_day__per_user_notes (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"group" character varying(128) NOT NULL,
|
||||||
|
___total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___dec smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___diffs_normal smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___diffs_reply smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___diffs_renote smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
"___diffs_withFile" smallint DEFAULT '0'::smallint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart_day__per_user_notes_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart_day__per_user_notes_id_seq OWNED BY public.__chart_day__per_user_notes.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart_day__per_user_reaction (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
"group" character varying(128) NOT NULL,
|
||||||
|
___local_count smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_count smallint DEFAULT '0'::bigint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart_day__per_user_reaction_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart_day__per_user_reaction_id_seq OWNED BY public.__chart_day__per_user_reaction.id;
|
||||||
|
|
||||||
|
CREATE TABLE public.__chart_day__users (
|
||||||
|
id integer NOT NULL,
|
||||||
|
date integer NOT NULL,
|
||||||
|
___local_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___local_dec smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_total integer DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_inc smallint DEFAULT '0'::bigint NOT NULL,
|
||||||
|
___remote_dec smallint DEFAULT '0'::bigint NOT NULL
|
||||||
|
);
|
||||||
|
CREATE SEQUENCE public.__chart_day__users_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
ALTER SEQUENCE public.__chart_day__users_id_seq OWNED BY public.__chart_day__users.id;
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ import { inspect } from "node:util";
|
||||||
* @callback BeforeShutdownListener
|
* @callback BeforeShutdownListener
|
||||||
* @param {string} [signalOrEvent] The exit signal or event name received on the process.
|
* @param {string} [signalOrEvent] The exit signal or event name received on the process.
|
||||||
*/
|
*/
|
||||||
|
type BeforeShutdownListener = (signalOrEvent: string) => PromiseLike<void>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* System signals the app will listen to initiate shutdown.
|
* System signals the app will listen to initiate shutdown.
|
||||||
|
@ -23,7 +24,7 @@ const SHUTDOWN_TIMEOUT = 15000;
|
||||||
* down the process.
|
* down the process.
|
||||||
* @type {BeforeShutdownListener[]}
|
* @type {BeforeShutdownListener[]}
|
||||||
*/
|
*/
|
||||||
const shutdownListeners: ((signalOrEvent: string) => void)[] = [];
|
const shutdownListeners: BeforeShutdownListener[] = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listen for signals and execute given `fn` function once.
|
* Listen for signals and execute given `fn` function once.
|
||||||
|
@ -86,7 +87,9 @@ async function shutdownHandler(signalOrEvent: string) {
|
||||||
* @param {BeforeShutdownListener} listener The shutdown listener to register.
|
* @param {BeforeShutdownListener} listener The shutdown listener to register.
|
||||||
* @returns {BeforeShutdownListener} Echoes back the supplied `listener`.
|
* @returns {BeforeShutdownListener} Echoes back the supplied `listener`.
|
||||||
*/
|
*/
|
||||||
export function beforeShutdown(listener: () => void) {
|
export function beforeShutdown(
|
||||||
|
listener: BeforeShutdownListener,
|
||||||
|
): BeforeShutdownListener {
|
||||||
shutdownListeners.push(listener);
|
shutdownListeners.push(listener);
|
||||||
return listener;
|
return listener;
|
||||||
}
|
}
|
||||||
|
|
|
@ -486,7 +486,9 @@ export const UserRepository = db.getRepository(User).extend({
|
||||||
url: profile!.url,
|
url: profile!.url,
|
||||||
uri: user.uri,
|
uri: user.uri,
|
||||||
movedToUri: user.movedToUri
|
movedToUri: user.movedToUri
|
||||||
? await this.userFromURI(user.movedToUri).catch(() => user.movedToUri)
|
? await this.userFromURI(user.movedToUri).catch(
|
||||||
|
() => user.movedToUri,
|
||||||
|
)
|
||||||
: null,
|
: null,
|
||||||
alsoKnownAs: user.alsoKnownAs,
|
alsoKnownAs: user.alsoKnownAs,
|
||||||
createdAt: user.createdAt.toISOString(),
|
createdAt: user.createdAt.toISOString(),
|
||||||
|
|
|
@ -528,24 +528,6 @@ export default function () {
|
||||||
processObjectStorage(objectStorageQueue);
|
processObjectStorage(objectStorageQueue);
|
||||||
processBackground(backgroundQueue);
|
processBackground(backgroundQueue);
|
||||||
|
|
||||||
systemQueue.add(
|
|
||||||
"tickCharts",
|
|
||||||
{},
|
|
||||||
{
|
|
||||||
repeat: { cron: "55 * * * *" },
|
|
||||||
removeOnComplete: true,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
systemQueue.add(
|
|
||||||
"resyncCharts",
|
|
||||||
{},
|
|
||||||
{
|
|
||||||
repeat: { cron: "0 0 * * *" },
|
|
||||||
removeOnComplete: true,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
systemQueue.add(
|
systemQueue.add(
|
||||||
"cleanCharts",
|
"cleanCharts",
|
||||||
{},
|
{},
|
||||||
|
|
|
@ -3,11 +3,6 @@ import request from "@/remote/activitypub/request.js";
|
||||||
import { registerOrFetchInstanceDoc } from "@/services/register-or-fetch-instance-doc.js";
|
import { registerOrFetchInstanceDoc } from "@/services/register-or-fetch-instance-doc.js";
|
||||||
import Logger from "@/services/logger.js";
|
import Logger from "@/services/logger.js";
|
||||||
import { Instances } from "@/models/index.js";
|
import { Instances } from "@/models/index.js";
|
||||||
import {
|
|
||||||
apRequestChart,
|
|
||||||
federationChart,
|
|
||||||
instanceChart,
|
|
||||||
} from "@/services/chart/index.js";
|
|
||||||
import { fetchInstanceMetadata } from "@/services/fetch-instance-metadata.js";
|
import { fetchInstanceMetadata } from "@/services/fetch-instance-metadata.js";
|
||||||
import { toPuny } from "@/misc/convert-host.js";
|
import { toPuny } from "@/misc/convert-host.js";
|
||||||
import { StatusError } from "@/misc/fetch.js";
|
import { StatusError } from "@/misc/fetch.js";
|
||||||
|
@ -42,10 +37,6 @@ export default async (job: Bull.Job<DeliverJobData>) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
fetchInstanceMetadata(i);
|
fetchInstanceMetadata(i);
|
||||||
|
|
||||||
instanceChart.requestSent(i.host, true);
|
|
||||||
apRequestChart.deliverSucc();
|
|
||||||
federationChart.deliverd(i.host, true);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return "Success";
|
return "Success";
|
||||||
|
@ -57,10 +48,6 @@ export default async (job: Bull.Job<DeliverJobData>) => {
|
||||||
latestStatus: res instanceof StatusError ? res.statusCode : null,
|
latestStatus: res instanceof StatusError ? res.statusCode : null,
|
||||||
isNotResponding: true,
|
isNotResponding: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
instanceChart.requestSent(i.host, false);
|
|
||||||
apRequestChart.deliverFail();
|
|
||||||
federationChart.deliverd(i.host, false);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (res instanceof StatusError) {
|
if (res instanceof StatusError) {
|
||||||
|
|
|
@ -5,11 +5,6 @@ import perform from "@/remote/activitypub/perform.js";
|
||||||
import Logger from "@/services/logger.js";
|
import Logger from "@/services/logger.js";
|
||||||
import { registerOrFetchInstanceDoc } from "@/services/register-or-fetch-instance-doc.js";
|
import { registerOrFetchInstanceDoc } from "@/services/register-or-fetch-instance-doc.js";
|
||||||
import { Instances } from "@/models/index.js";
|
import { Instances } from "@/models/index.js";
|
||||||
import {
|
|
||||||
apRequestChart,
|
|
||||||
federationChart,
|
|
||||||
instanceChart,
|
|
||||||
} from "@/services/chart/index.js";
|
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||||
import { toPuny, extractDbHost } from "@/misc/convert-host.js";
|
import { toPuny, extractDbHost } from "@/misc/convert-host.js";
|
||||||
import { getApId } from "@/remote/activitypub/type.js";
|
import { getApId } from "@/remote/activitypub/type.js";
|
||||||
|
@ -189,10 +184,6 @@ export default async (job: Bull.Job<InboxJobData>): Promise<string> => {
|
||||||
});
|
});
|
||||||
|
|
||||||
fetchInstanceMetadata(i);
|
fetchInstanceMetadata(i);
|
||||||
|
|
||||||
instanceChart.requestReceived(i.host);
|
|
||||||
apRequestChart.inbox();
|
|
||||||
federationChart.inbox(i.host);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// アクティビティを処理
|
// アクティビティを処理
|
||||||
|
|
|
@ -1,20 +1,7 @@
|
||||||
import type Bull from "bull";
|
import type Bull from "bull";
|
||||||
|
|
||||||
import { queueLogger } from "../../logger.js";
|
import { queueLogger } from "../../logger.js";
|
||||||
import {
|
import { activeUsersChart } from "@/services/chart/index.js";
|
||||||
activeUsersChart,
|
|
||||||
driveChart,
|
|
||||||
federationChart,
|
|
||||||
hashtagChart,
|
|
||||||
instanceChart,
|
|
||||||
notesChart,
|
|
||||||
perUserDriveChart,
|
|
||||||
perUserFollowingChart,
|
|
||||||
perUserNotesChart,
|
|
||||||
perUserReactionsChart,
|
|
||||||
usersChart,
|
|
||||||
apRequestChart,
|
|
||||||
} from "@/services/chart/index.js";
|
|
||||||
|
|
||||||
const logger = queueLogger.createSubLogger("clean-charts");
|
const logger = queueLogger.createSubLogger("clean-charts");
|
||||||
|
|
||||||
|
@ -22,23 +9,8 @@ export async function cleanCharts(
|
||||||
job: Bull.Job<Record<string, unknown>>,
|
job: Bull.Job<Record<string, unknown>>,
|
||||||
done: any,
|
done: any,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
logger.info("Clean charts...");
|
logger.info("Cleaning active users chart...");
|
||||||
|
await activeUsersChart.clean();
|
||||||
await Promise.all([
|
logger.succ("Active users chart has been cleaned.");
|
||||||
federationChart.clean(),
|
|
||||||
notesChart.clean(),
|
|
||||||
usersChart.clean(),
|
|
||||||
activeUsersChart.clean(),
|
|
||||||
instanceChart.clean(),
|
|
||||||
perUserNotesChart.clean(),
|
|
||||||
driveChart.clean(),
|
|
||||||
perUserReactionsChart.clean(),
|
|
||||||
hashtagChart.clean(),
|
|
||||||
perUserFollowingChart.clean(),
|
|
||||||
perUserDriveChart.clean(),
|
|
||||||
apRequestChart.clean(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
logger.succ("All charts successfully cleaned.");
|
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
import type Bull from "bull";
|
import type Bull from "bull";
|
||||||
import { tickCharts } from "./tick-charts.js";
|
|
||||||
import { resyncCharts } from "./resync-charts.js";
|
|
||||||
import { cleanCharts } from "./clean-charts.js";
|
import { cleanCharts } from "./clean-charts.js";
|
||||||
import { checkExpiredMutings } from "./check-expired-mutings.js";
|
import { checkExpiredMutings } from "./check-expired-mutings.js";
|
||||||
import { clean } from "./clean.js";
|
import { clean } from "./clean.js";
|
||||||
|
@ -8,8 +6,6 @@ import { setLocalEmojiSizes } from "./local-emoji-size.js";
|
||||||
import { verifyLinks } from "./verify-links.js";
|
import { verifyLinks } from "./verify-links.js";
|
||||||
|
|
||||||
const jobs = {
|
const jobs = {
|
||||||
tickCharts,
|
|
||||||
resyncCharts,
|
|
||||||
cleanCharts,
|
cleanCharts,
|
||||||
checkExpiredMutings,
|
checkExpiredMutings,
|
||||||
clean,
|
clean,
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
import type Bull from "bull";
|
|
||||||
|
|
||||||
import { queueLogger } from "../../logger.js";
|
|
||||||
import { driveChart, notesChart, usersChart } from "@/services/chart/index.js";
|
|
||||||
|
|
||||||
const logger = queueLogger.createSubLogger("resync-charts");
|
|
||||||
|
|
||||||
export async function resyncCharts(
|
|
||||||
job: Bull.Job<Record<string, unknown>>,
|
|
||||||
done: any,
|
|
||||||
): Promise<void> {
|
|
||||||
logger.info("Resync charts...");
|
|
||||||
|
|
||||||
// TODO: ユーザーごとのチャートも更新する
|
|
||||||
// TODO: インスタンスごとのチャートも更新する
|
|
||||||
await Promise.all([
|
|
||||||
driveChart.resync(),
|
|
||||||
notesChart.resync(),
|
|
||||||
usersChart.resync(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
logger.succ("All charts successfully resynced.");
|
|
||||||
done();
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
import type Bull from "bull";
|
|
||||||
|
|
||||||
import { queueLogger } from "../../logger.js";
|
|
||||||
import {
|
|
||||||
activeUsersChart,
|
|
||||||
driveChart,
|
|
||||||
federationChart,
|
|
||||||
hashtagChart,
|
|
||||||
instanceChart,
|
|
||||||
notesChart,
|
|
||||||
perUserDriveChart,
|
|
||||||
perUserFollowingChart,
|
|
||||||
perUserNotesChart,
|
|
||||||
perUserReactionsChart,
|
|
||||||
usersChart,
|
|
||||||
apRequestChart,
|
|
||||||
} from "@/services/chart/index.js";
|
|
||||||
|
|
||||||
const logger = queueLogger.createSubLogger("tick-charts");
|
|
||||||
|
|
||||||
export async function tickCharts(
|
|
||||||
job: Bull.Job<Record<string, unknown>>,
|
|
||||||
done: any,
|
|
||||||
): Promise<void> {
|
|
||||||
logger.info("Tick charts...");
|
|
||||||
|
|
||||||
await Promise.all([
|
|
||||||
federationChart.tick(false),
|
|
||||||
notesChart.tick(false),
|
|
||||||
usersChart.tick(false),
|
|
||||||
activeUsersChart.tick(false),
|
|
||||||
instanceChart.tick(false),
|
|
||||||
perUserNotesChart.tick(false),
|
|
||||||
driveChart.tick(false),
|
|
||||||
perUserReactionsChart.tick(false),
|
|
||||||
hashtagChart.tick(false),
|
|
||||||
perUserFollowingChart.tick(false),
|
|
||||||
perUserDriveChart.tick(false),
|
|
||||||
apRequestChart.tick(false),
|
|
||||||
]);
|
|
||||||
|
|
||||||
logger.succ("All charts successfully ticked.");
|
|
||||||
done();
|
|
||||||
}
|
|
|
@ -17,7 +17,6 @@ import { User } from "@/models/entities/user.js";
|
||||||
import type { Emoji } from "@/models/entities/emoji.js";
|
import type { Emoji } from "@/models/entities/emoji.js";
|
||||||
import { UserNotePining } from "@/models/entities/user-note-pining.js";
|
import { UserNotePining } from "@/models/entities/user-note-pining.js";
|
||||||
import { genId } from "@/misc/gen-id.js";
|
import { genId } from "@/misc/gen-id.js";
|
||||||
import { instanceChart, usersChart } from "@/services/chart/index.js";
|
|
||||||
import { UserPublickey } from "@/models/entities/user-publickey.js";
|
import { UserPublickey } from "@/models/entities/user-publickey.js";
|
||||||
import { isDuplicateKeyValueError } from "@/misc/is-duplicate-key-value-error.js";
|
import { isDuplicateKeyValueError } from "@/misc/is-duplicate-key-value-error.js";
|
||||||
import { toPuny } from "@/misc/convert-host.js";
|
import { toPuny } from "@/misc/convert-host.js";
|
||||||
|
@ -358,12 +357,9 @@ export async function createPerson(
|
||||||
// Register host
|
// Register host
|
||||||
registerOrFetchInstanceDoc(host).then((i) => {
|
registerOrFetchInstanceDoc(host).then((i) => {
|
||||||
Instances.increment({ id: i.id }, "usersCount", 1);
|
Instances.increment({ id: i.id }, "usersCount", 1);
|
||||||
instanceChart.newUser(i.host);
|
|
||||||
fetchInstanceMetadata(i);
|
fetchInstanceMetadata(i);
|
||||||
});
|
});
|
||||||
|
|
||||||
usersChart.update(user!, true);
|
|
||||||
|
|
||||||
// Hashtag update
|
// Hashtag update
|
||||||
updateUsertags(user!, tags);
|
updateUsertags(user!, tags);
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@ import { IsNull } from "typeorm";
|
||||||
import { genId } from "@/misc/gen-id.js";
|
import { genId } from "@/misc/gen-id.js";
|
||||||
import { toPunyNullable } from "@/misc/convert-host.js";
|
import { toPunyNullable } from "@/misc/convert-host.js";
|
||||||
import { UserKeypair } from "@/models/entities/user-keypair.js";
|
import { UserKeypair } from "@/models/entities/user-keypair.js";
|
||||||
import { usersChart } from "@/services/chart/index.js";
|
|
||||||
import { UsedUsername } from "@/models/entities/used-username.js";
|
import { UsedUsername } from "@/models/entities/used-username.js";
|
||||||
import { db } from "@/db/postgre.js";
|
import { db } from "@/db/postgre.js";
|
||||||
import config from "@/config/index.js";
|
import config from "@/config/index.js";
|
||||||
|
@ -135,7 +134,5 @@ export async function signup(opts: {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
usersChart.update(account, true);
|
|
||||||
|
|
||||||
return { account, secret };
|
return { account, secret };
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,17 +99,6 @@ import * as ep___channels_timeline from "./endpoints/channels/timeline.js";
|
||||||
import * as ep___channels_unfollow from "./endpoints/channels/unfollow.js";
|
import * as ep___channels_unfollow from "./endpoints/channels/unfollow.js";
|
||||||
import * as ep___channels_update from "./endpoints/channels/update.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_drive from "./endpoints/charts/drive.js";
|
|
||||||
import * as ep___charts_federation from "./endpoints/charts/federation.js";
|
|
||||||
import * as ep___charts_hashtag from "./endpoints/charts/hashtag.js";
|
|
||||||
import * as ep___charts_instance from "./endpoints/charts/instance.js";
|
|
||||||
import * as ep___charts_notes from "./endpoints/charts/notes.js";
|
|
||||||
import * as ep___charts_user_drive from "./endpoints/charts/user/drive.js";
|
|
||||||
import * as ep___charts_user_following from "./endpoints/charts/user/following.js";
|
|
||||||
import * as ep___charts_user_notes from "./endpoints/charts/user/notes.js";
|
|
||||||
import * as ep___charts_user_reactions from "./endpoints/charts/user/reactions.js";
|
|
||||||
import * as ep___charts_users from "./endpoints/charts/users.js";
|
|
||||||
import * as ep___clips_addNote from "./endpoints/clips/add-note.js";
|
import * as ep___clips_addNote from "./endpoints/clips/add-note.js";
|
||||||
import * as ep___clips_removeNote from "./endpoints/clips/remove-note.js";
|
import * as ep___clips_removeNote from "./endpoints/clips/remove-note.js";
|
||||||
import * as ep___clips_create from "./endpoints/clips/create.js";
|
import * as ep___clips_create from "./endpoints/clips/create.js";
|
||||||
|
@ -457,17 +446,6 @@ const eps = [
|
||||||
["channels/unfollow", ep___channels_unfollow],
|
["channels/unfollow", ep___channels_unfollow],
|
||||||
["channels/update", ep___channels_update],
|
["channels/update", ep___channels_update],
|
||||||
["charts/active-users", ep___charts_activeUsers],
|
["charts/active-users", ep___charts_activeUsers],
|
||||||
["charts/ap-request", ep___charts_apRequest],
|
|
||||||
["charts/drive", ep___charts_drive],
|
|
||||||
["charts/federation", ep___charts_federation],
|
|
||||||
["charts/hashtag", ep___charts_hashtag],
|
|
||||||
["charts/instance", ep___charts_instance],
|
|
||||||
["charts/notes", ep___charts_notes],
|
|
||||||
["charts/user/drive", ep___charts_user_drive],
|
|
||||||
["charts/user/following", ep___charts_user_following],
|
|
||||||
["charts/user/notes", ep___charts_user_notes],
|
|
||||||
["charts/user/reactions", ep___charts_user_reactions],
|
|
||||||
["charts/users", ep___charts_users],
|
|
||||||
["clips/add-note", ep___clips_addNote],
|
["clips/add-note", ep___clips_addNote],
|
||||||
["clips/remove-note", ep___clips_removeNote],
|
["clips/remove-note", ep___clips_removeNote],
|
||||||
["clips/create", ep___clips_create],
|
["clips/create", ep___clips_create],
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
import { getJsonSchema } from "@/services/chart/core.js";
|
|
||||||
import { apRequestChart } from "@/services/chart/index.js";
|
|
||||||
import define from "@/server/api/define.js";
|
|
||||||
|
|
||||||
export const meta = {
|
|
||||||
tags: ["charts"],
|
|
||||||
requireCredentialPrivateMode: true,
|
|
||||||
|
|
||||||
res: getJsonSchema(apRequestChart.schema),
|
|
||||||
|
|
||||||
allowGet: true,
|
|
||||||
cacheSec: 60 * 60,
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const paramDef = {
|
|
||||||
type: "object",
|
|
||||||
properties: {
|
|
||||||
span: { type: "string", enum: ["day", "hour"] },
|
|
||||||
limit: { type: "integer", minimum: 1, maximum: 500, default: 30 },
|
|
||||||
offset: { type: "integer", nullable: true, default: null },
|
|
||||||
},
|
|
||||||
required: ["span"],
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export default define(meta, paramDef, async (ps) => {
|
|
||||||
return await apRequestChart.getChart(
|
|
||||||
ps.span,
|
|
||||||
ps.limit,
|
|
||||||
ps.offset ? new Date(ps.offset) : null,
|
|
||||||
);
|
|
||||||
});
|
|
|
@ -1,31 +0,0 @@
|
||||||
import { getJsonSchema } from "@/services/chart/core.js";
|
|
||||||
import { driveChart } from "@/services/chart/index.js";
|
|
||||||
import define from "@/server/api/define.js";
|
|
||||||
|
|
||||||
export const meta = {
|
|
||||||
tags: ["charts", "drive"],
|
|
||||||
requireCredentialPrivateMode: true,
|
|
||||||
|
|
||||||
res: getJsonSchema(driveChart.schema),
|
|
||||||
|
|
||||||
allowGet: true,
|
|
||||||
cacheSec: 60 * 60,
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const paramDef = {
|
|
||||||
type: "object",
|
|
||||||
properties: {
|
|
||||||
span: { type: "string", enum: ["day", "hour"] },
|
|
||||||
limit: { type: "integer", minimum: 1, maximum: 500, default: 30 },
|
|
||||||
offset: { type: "integer", nullable: true, default: null },
|
|
||||||
},
|
|
||||||
required: ["span"],
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export default define(meta, paramDef, async (ps) => {
|
|
||||||
return await driveChart.getChart(
|
|
||||||
ps.span,
|
|
||||||
ps.limit,
|
|
||||||
ps.offset ? new Date(ps.offset) : null,
|
|
||||||
);
|
|
||||||
});
|
|
|
@ -1,31 +0,0 @@
|
||||||
import { getJsonSchema } from "@/services/chart/core.js";
|
|
||||||
import { federationChart } from "@/services/chart/index.js";
|
|
||||||
import define from "@/server/api/define.js";
|
|
||||||
|
|
||||||
export const meta = {
|
|
||||||
tags: ["charts"],
|
|
||||||
requireCredentialPrivateMode: true,
|
|
||||||
|
|
||||||
res: getJsonSchema(federationChart.schema),
|
|
||||||
|
|
||||||
allowGet: true,
|
|
||||||
cacheSec: 60 * 60,
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const paramDef = {
|
|
||||||
type: "object",
|
|
||||||
properties: {
|
|
||||||
span: { type: "string", enum: ["day", "hour"] },
|
|
||||||
limit: { type: "integer", minimum: 1, maximum: 500, default: 30 },
|
|
||||||
offset: { type: "integer", nullable: true, default: null },
|
|
||||||
},
|
|
||||||
required: ["span"],
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export default define(meta, paramDef, async (ps) => {
|
|
||||||
return await federationChart.getChart(
|
|
||||||
ps.span,
|
|
||||||
ps.limit,
|
|
||||||
ps.offset ? new Date(ps.offset) : null,
|
|
||||||
);
|
|
||||||
});
|
|
|
@ -1,33 +0,0 @@
|
||||||
import { getJsonSchema } from "@/services/chart/core.js";
|
|
||||||
import { hashtagChart } from "@/services/chart/index.js";
|
|
||||||
import define from "@/server/api/define.js";
|
|
||||||
|
|
||||||
export const meta = {
|
|
||||||
tags: ["charts", "hashtags"],
|
|
||||||
requireCredentialPrivateMode: true,
|
|
||||||
|
|
||||||
res: getJsonSchema(hashtagChart.schema),
|
|
||||||
|
|
||||||
allowGet: true,
|
|
||||||
cacheSec: 60 * 60,
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const paramDef = {
|
|
||||||
type: "object",
|
|
||||||
properties: {
|
|
||||||
span: { type: "string", enum: ["day", "hour"] },
|
|
||||||
limit: { type: "integer", minimum: 1, maximum: 500, default: 30 },
|
|
||||||
offset: { type: "integer", nullable: true, default: null },
|
|
||||||
tag: { type: "string" },
|
|
||||||
},
|
|
||||||
required: ["span", "tag"],
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export default define(meta, paramDef, async (ps) => {
|
|
||||||
return await hashtagChart.getChart(
|
|
||||||
ps.span,
|
|
||||||
ps.limit,
|
|
||||||
ps.offset ? new Date(ps.offset) : null,
|
|
||||||
ps.tag,
|
|
||||||
);
|
|
||||||
});
|
|
|
@ -1,33 +0,0 @@
|
||||||
import { getJsonSchema } from "@/services/chart/core.js";
|
|
||||||
import { instanceChart } from "@/services/chart/index.js";
|
|
||||||
import define from "@/server/api/define.js";
|
|
||||||
|
|
||||||
export const meta = {
|
|
||||||
tags: ["charts"],
|
|
||||||
requireCredentialPrivateMode: true,
|
|
||||||
|
|
||||||
res: getJsonSchema(instanceChart.schema),
|
|
||||||
|
|
||||||
allowGet: true,
|
|
||||||
cacheSec: 60 * 60,
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const paramDef = {
|
|
||||||
type: "object",
|
|
||||||
properties: {
|
|
||||||
span: { type: "string", enum: ["day", "hour"] },
|
|
||||||
limit: { type: "integer", minimum: 1, maximum: 500, default: 30 },
|
|
||||||
offset: { type: "integer", nullable: true, default: null },
|
|
||||||
host: { type: "string" },
|
|
||||||
},
|
|
||||||
required: ["span", "host"],
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export default define(meta, paramDef, async (ps) => {
|
|
||||||
return await instanceChart.getChart(
|
|
||||||
ps.span,
|
|
||||||
ps.limit,
|
|
||||||
ps.offset ? new Date(ps.offset) : null,
|
|
||||||
ps.host,
|
|
||||||
);
|
|
||||||
});
|
|
|
@ -1,31 +0,0 @@
|
||||||
import { getJsonSchema } from "@/services/chart/core.js";
|
|
||||||
import { notesChart } from "@/services/chart/index.js";
|
|
||||||
import define from "@/server/api/define.js";
|
|
||||||
|
|
||||||
export const meta = {
|
|
||||||
tags: ["charts", "notes"],
|
|
||||||
requireCredentialPrivateMode: true,
|
|
||||||
|
|
||||||
res: getJsonSchema(notesChart.schema),
|
|
||||||
|
|
||||||
allowGet: true,
|
|
||||||
cacheSec: 60 * 60,
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const paramDef = {
|
|
||||||
type: "object",
|
|
||||||
properties: {
|
|
||||||
span: { type: "string", enum: ["day", "hour"] },
|
|
||||||
limit: { type: "integer", minimum: 1, maximum: 500, default: 30 },
|
|
||||||
offset: { type: "integer", nullable: true, default: null },
|
|
||||||
},
|
|
||||||
required: ["span"],
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export default define(meta, paramDef, async (ps) => {
|
|
||||||
return await notesChart.getChart(
|
|
||||||
ps.span,
|
|
||||||
ps.limit,
|
|
||||||
ps.offset ? new Date(ps.offset) : null,
|
|
||||||
);
|
|
||||||
});
|
|
|
@ -1,33 +0,0 @@
|
||||||
import { getJsonSchema } from "@/services/chart/core.js";
|
|
||||||
import { perUserDriveChart } from "@/services/chart/index.js";
|
|
||||||
import define from "@/server/api/define.js";
|
|
||||||
|
|
||||||
export const meta = {
|
|
||||||
tags: ["charts", "drive", "users"],
|
|
||||||
requireCredentialPrivateMode: true,
|
|
||||||
|
|
||||||
res: getJsonSchema(perUserDriveChart.schema),
|
|
||||||
|
|
||||||
allowGet: true,
|
|
||||||
cacheSec: 60 * 60,
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const paramDef = {
|
|
||||||
type: "object",
|
|
||||||
properties: {
|
|
||||||
span: { type: "string", enum: ["day", "hour"] },
|
|
||||||
limit: { type: "integer", minimum: 1, maximum: 500, default: 30 },
|
|
||||||
offset: { type: "integer", nullable: true, default: null },
|
|
||||||
userId: { type: "string", format: "misskey:id" },
|
|
||||||
},
|
|
||||||
required: ["span", "userId"],
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export default define(meta, paramDef, async (ps) => {
|
|
||||||
return await perUserDriveChart.getChart(
|
|
||||||
ps.span,
|
|
||||||
ps.limit,
|
|
||||||
ps.offset ? new Date(ps.offset) : null,
|
|
||||||
ps.userId,
|
|
||||||
);
|
|
||||||
});
|
|
|
@ -1,33 +0,0 @@
|
||||||
import define from "@/server/api/define.js";
|
|
||||||
import { getJsonSchema } from "@/services/chart/core.js";
|
|
||||||
import { perUserFollowingChart } from "@/services/chart/index.js";
|
|
||||||
|
|
||||||
export const meta = {
|
|
||||||
tags: ["charts", "users", "following"],
|
|
||||||
requireCredentialPrivateMode: true,
|
|
||||||
|
|
||||||
res: getJsonSchema(perUserFollowingChart.schema),
|
|
||||||
|
|
||||||
allowGet: true,
|
|
||||||
cacheSec: 60 * 60,
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const paramDef = {
|
|
||||||
type: "object",
|
|
||||||
properties: {
|
|
||||||
span: { type: "string", enum: ["day", "hour"] },
|
|
||||||
limit: { type: "integer", minimum: 1, maximum: 500, default: 30 },
|
|
||||||
offset: { type: "integer", nullable: true, default: null },
|
|
||||||
userId: { type: "string", format: "misskey:id" },
|
|
||||||
},
|
|
||||||
required: ["span", "userId"],
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export default define(meta, paramDef, async (ps) => {
|
|
||||||
return await perUserFollowingChart.getChart(
|
|
||||||
ps.span,
|
|
||||||
ps.limit,
|
|
||||||
ps.offset ? new Date(ps.offset) : null,
|
|
||||||
ps.userId,
|
|
||||||
);
|
|
||||||
});
|
|
|
@ -1,33 +0,0 @@
|
||||||
import { getJsonSchema } from "@/services/chart/core.js";
|
|
||||||
import { perUserNotesChart } from "@/services/chart/index.js";
|
|
||||||
import define from "@/server/api/define.js";
|
|
||||||
|
|
||||||
export const meta = {
|
|
||||||
tags: ["charts", "users", "notes"],
|
|
||||||
requireCredentialPrivateMode: true,
|
|
||||||
|
|
||||||
res: getJsonSchema(perUserNotesChart.schema),
|
|
||||||
|
|
||||||
allowGet: true,
|
|
||||||
cacheSec: 60 * 60,
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const paramDef = {
|
|
||||||
type: "object",
|
|
||||||
properties: {
|
|
||||||
span: { type: "string", enum: ["day", "hour"] },
|
|
||||||
limit: { type: "integer", minimum: 1, maximum: 500, default: 30 },
|
|
||||||
offset: { type: "integer", nullable: true, default: null },
|
|
||||||
userId: { type: "string", format: "misskey:id" },
|
|
||||||
},
|
|
||||||
required: ["span", "userId"],
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export default define(meta, paramDef, async (ps) => {
|
|
||||||
return await perUserNotesChart.getChart(
|
|
||||||
ps.span,
|
|
||||||
ps.limit,
|
|
||||||
ps.offset ? new Date(ps.offset) : null,
|
|
||||||
ps.userId,
|
|
||||||
);
|
|
||||||
});
|
|
|
@ -1,33 +0,0 @@
|
||||||
import { getJsonSchema } from "@/services/chart/core.js";
|
|
||||||
import { perUserReactionsChart } from "@/services/chart/index.js";
|
|
||||||
import define from "@/server/api/define.js";
|
|
||||||
|
|
||||||
export const meta = {
|
|
||||||
tags: ["charts", "users", "reactions"],
|
|
||||||
requireCredentialPrivateMode: true,
|
|
||||||
|
|
||||||
res: getJsonSchema(perUserReactionsChart.schema),
|
|
||||||
|
|
||||||
allowGet: true,
|
|
||||||
cacheSec: 60 * 60,
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const paramDef = {
|
|
||||||
type: "object",
|
|
||||||
properties: {
|
|
||||||
span: { type: "string", enum: ["day", "hour"] },
|
|
||||||
limit: { type: "integer", minimum: 1, maximum: 500, default: 30 },
|
|
||||||
offset: { type: "integer", nullable: true, default: null },
|
|
||||||
userId: { type: "string", format: "misskey:id" },
|
|
||||||
},
|
|
||||||
required: ["span", "userId"],
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export default define(meta, paramDef, async (ps) => {
|
|
||||||
return await perUserReactionsChart.getChart(
|
|
||||||
ps.span,
|
|
||||||
ps.limit,
|
|
||||||
ps.offset ? new Date(ps.offset) : null,
|
|
||||||
ps.userId,
|
|
||||||
);
|
|
||||||
});
|
|
|
@ -1,31 +0,0 @@
|
||||||
import { getJsonSchema } from "@/services/chart/core.js";
|
|
||||||
import { usersChart } from "@/services/chart/index.js";
|
|
||||||
import define from "@/server/api/define.js";
|
|
||||||
|
|
||||||
export const meta = {
|
|
||||||
tags: ["charts", "users"],
|
|
||||||
requireCredentialPrivateMode: true,
|
|
||||||
|
|
||||||
res: getJsonSchema(usersChart.schema),
|
|
||||||
|
|
||||||
allowGet: true,
|
|
||||||
cacheSec: 60 * 60,
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const paramDef = {
|
|
||||||
type: "object",
|
|
||||||
properties: {
|
|
||||||
span: { type: "string", enum: ["day", "hour"] },
|
|
||||||
limit: { type: "integer", minimum: 1, maximum: 500, default: 30 },
|
|
||||||
offset: { type: "integer", nullable: true, default: null },
|
|
||||||
},
|
|
||||||
required: ["span"],
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export default define(meta, paramDef, async (ps) => {
|
|
||||||
return await usersChart.getChart(
|
|
||||||
ps.span,
|
|
||||||
ps.limit,
|
|
||||||
ps.offset ? new Date(ps.offset) : null,
|
|
||||||
);
|
|
||||||
});
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Instances, NoteReactions, Notes, Users } from "@/models/index.js";
|
import { Instances, Users, Notes } from "@/models/index.js";
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
import { driveChart, notesChart, usersChart } from "@/services/chart/index.js";
|
import { IsNull } from "typeorm";
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
requireCredential: false,
|
requireCredential: false,
|
||||||
|
@ -8,6 +8,8 @@ export const meta = {
|
||||||
|
|
||||||
tags: ["meta"],
|
tags: ["meta"],
|
||||||
|
|
||||||
|
cacheSec: 600,
|
||||||
|
|
||||||
res: {
|
res: {
|
||||||
type: "object",
|
type: "object",
|
||||||
optional: false,
|
optional: false,
|
||||||
|
@ -38,16 +40,6 @@ export const meta = {
|
||||||
optional: false,
|
optional: false,
|
||||||
nullable: false,
|
nullable: false,
|
||||||
},
|
},
|
||||||
driveUsageLocal: {
|
|
||||||
type: "number",
|
|
||||||
optional: false,
|
|
||||||
nullable: false,
|
|
||||||
},
|
|
||||||
driveUsageRemote: {
|
|
||||||
type: "number",
|
|
||||||
optional: false,
|
|
||||||
nullable: false,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
@ -59,28 +51,31 @@ export const paramDef = {
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export default define(meta, paramDef, async () => {
|
export default define(meta, paramDef, async () => {
|
||||||
const notesChartData = await notesChart.getChart("hour", 1, null);
|
|
||||||
const notesCount =
|
|
||||||
notesChartData.local.total[0] + notesChartData.remote.total[0];
|
|
||||||
const originalNotesCount = notesChartData.local.total[0];
|
|
||||||
|
|
||||||
const usersChartData = await usersChart.getChart("hour", 1, null);
|
|
||||||
const usersCount =
|
|
||||||
usersChartData.local.total[0] + usersChartData.remote.total[0];
|
|
||||||
const originalUsersCount = usersChartData.local.total[0];
|
|
||||||
const driveChartData = await driveChart.getChart("hour", 1, null);
|
|
||||||
//TODO: fixme currently returns 0
|
|
||||||
const driveUsageLocal = driveChartData.local.incSize[0];
|
|
||||||
const driveUsageRemote = driveChartData.remote.incSize[0];
|
|
||||||
|
|
||||||
const [
|
const [
|
||||||
reactionsCount,
|
notesCount,
|
||||||
//originalReactionsCount,
|
originalNotesCount,
|
||||||
|
usersCount,
|
||||||
|
originalUsersCount,
|
||||||
instances,
|
instances,
|
||||||
] = await Promise.all([
|
] = await Promise.all([
|
||||||
NoteReactions.count({ cache: 3600000 }), // 1 hour
|
// notesCount
|
||||||
//NoteReactions.count({ where: { userHost: IsNull() }, cache: 3600000 }),
|
Notes.count(),
|
||||||
Instances.count({ cache: 3600000 }),
|
// originalNotesCount
|
||||||
|
Notes.count({
|
||||||
|
where: {
|
||||||
|
userHost: IsNull(),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
// usersCount
|
||||||
|
Users.count(),
|
||||||
|
// originalUsersCount
|
||||||
|
Users.count({
|
||||||
|
where: {
|
||||||
|
host: IsNull(),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
// instances
|
||||||
|
Instances.count(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -88,10 +83,6 @@ export default define(meta, paramDef, async () => {
|
||||||
originalNotesCount,
|
originalNotesCount,
|
||||||
usersCount,
|
usersCount,
|
||||||
originalUsersCount,
|
originalUsersCount,
|
||||||
reactionsCount,
|
|
||||||
//originalReactionsCount,
|
|
||||||
instances,
|
instances,
|
||||||
driveUsageLocal,
|
|
||||||
driveUsageRemote,
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
@ -15,7 +15,6 @@ import {
|
||||||
UserListJoinings,
|
UserListJoinings,
|
||||||
UserLists,
|
UserLists,
|
||||||
} from "@/models/index.js";
|
} from "@/models/index.js";
|
||||||
import { perUserFollowingChart } from "@/services/chart/index.js";
|
|
||||||
import { genId } from "@/misc/gen-id.js";
|
import { genId } from "@/misc/gen-id.js";
|
||||||
import { getActiveWebhooks } from "@/misc/webhook-cache.js";
|
import { getActiveWebhooks } from "@/misc/webhook-cache.js";
|
||||||
import { webhookDeliver } from "@/queue/index.js";
|
import { webhookDeliver } from "@/queue/index.js";
|
||||||
|
@ -119,7 +118,6 @@ async function unFollow(follower: User, followee: User) {
|
||||||
Followings.delete(following.id),
|
Followings.delete(following.id),
|
||||||
Users.decrement({ id: follower.id }, "followingCount", 1),
|
Users.decrement({ id: follower.id }, "followingCount", 1),
|
||||||
Users.decrement({ id: followee.id }, "followersCount", 1),
|
Users.decrement({ id: followee.id }, "followersCount", 1),
|
||||||
perUserFollowingChart.update(follower, followee, false),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Publish unfollow event
|
// Publish unfollow event
|
||||||
|
|
|
@ -16,14 +16,6 @@ export default class ActiveUsersChart extends Chart<typeof schema> {
|
||||||
super(name, schema);
|
super(name, schema);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async tickMinor(): Promise<Partial<KVs<typeof schema>>> {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
public read(user: {
|
public read(user: {
|
||||||
id: User["id"];
|
id: User["id"];
|
||||||
host: null;
|
host: null;
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
import type { KVs } from "../core.js";
|
|
||||||
import Chart from "../core.js";
|
|
||||||
import { name, schema } from "./entities/ap-request.js";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Chart about ActivityPub requests
|
|
||||||
*/
|
|
||||||
|
|
||||||
export default class ApRequestChart extends Chart<typeof schema> {
|
|
||||||
constructor() {
|
|
||||||
super(name, schema);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async tickMinor(): Promise<Partial<KVs<typeof schema>>> {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
public async deliverSucc(): Promise<void> {
|
|
||||||
await this.commit({
|
|
||||||
deliverSucceeded: 1,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public async deliverFail(): Promise<void> {
|
|
||||||
await this.commit({
|
|
||||||
deliverFailed: 1,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public async inbox(): Promise<void> {
|
|
||||||
await this.commit({
|
|
||||||
inboxReceived: 1,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
import type { KVs } from "../core.js";
|
|
||||||
import Chart from "../core.js";
|
|
||||||
import type { DriveFile } from "@/models/entities/drive-file.js";
|
|
||||||
import { name, schema } from "./entities/drive.js";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ドライブに関するチャート
|
|
||||||
*/
|
|
||||||
|
|
||||||
export default class DriveChart extends Chart<typeof schema> {
|
|
||||||
constructor() {
|
|
||||||
super(name, schema);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async tickMinor(): Promise<Partial<KVs<typeof schema>>> {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
public async update(file: DriveFile, isAdditional: boolean): Promise<void> {
|
|
||||||
const fileSizeKb = file.size / 1000;
|
|
||||||
await this.commit(
|
|
||||||
file.userHost === null
|
|
||||||
? {
|
|
||||||
"local.incCount": isAdditional ? 1 : 0,
|
|
||||||
"local.incSize": isAdditional ? fileSizeKb : 0,
|
|
||||||
"local.decCount": isAdditional ? 0 : 1,
|
|
||||||
"local.decSize": isAdditional ? 0 : fileSizeKb,
|
|
||||||
}
|
|
||||||
: {
|
|
||||||
"remote.incCount": isAdditional ? 1 : 0,
|
|
||||||
"remote.incSize": isAdditional ? fileSizeKb : 0,
|
|
||||||
"remote.decCount": isAdditional ? 0 : 1,
|
|
||||||
"remote.decSize": isAdditional ? 0 : fileSizeKb,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
import Chart from "../../core.js";
|
|
||||||
|
|
||||||
export const name = "apRequest";
|
|
||||||
|
|
||||||
export const schema = {
|
|
||||||
deliverFailed: {},
|
|
||||||
deliverSucceeded: {},
|
|
||||||
inboxReceived: {},
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const entity = Chart.schemaToEntity(name, schema);
|
|
|
@ -1,16 +0,0 @@
|
||||||
import Chart from "../../core.js";
|
|
||||||
|
|
||||||
export const name = "drive";
|
|
||||||
|
|
||||||
export const schema = {
|
|
||||||
"local.incCount": {},
|
|
||||||
"local.incSize": {}, // in kilobyte
|
|
||||||
"local.decCount": {},
|
|
||||||
"local.decSize": {}, // in kilobyte
|
|
||||||
"remote.incCount": {},
|
|
||||||
"remote.incSize": {}, // in kilobyte
|
|
||||||
"remote.decCount": {},
|
|
||||||
"remote.decSize": {}, // in kilobyte
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const entity = Chart.schemaToEntity(name, schema);
|
|
|
@ -1,16 +0,0 @@
|
||||||
import Chart from "../../core.js";
|
|
||||||
|
|
||||||
export const name = "federation";
|
|
||||||
|
|
||||||
export const schema = {
|
|
||||||
deliveredInstances: { uniqueIncrement: true, range: "small" },
|
|
||||||
inboxInstances: { uniqueIncrement: true, range: "small" },
|
|
||||||
stalled: { uniqueIncrement: true, range: "small" },
|
|
||||||
sub: { accumulate: true, range: "small" },
|
|
||||||
pub: { accumulate: true, range: "small" },
|
|
||||||
pubsub: { accumulate: true, range: "small" },
|
|
||||||
subActive: { accumulate: true, range: "small" },
|
|
||||||
pubActive: { accumulate: true, range: "small" },
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const entity = Chart.schemaToEntity(name, schema);
|
|
|
@ -1,10 +0,0 @@
|
||||||
import Chart from "../../core.js";
|
|
||||||
|
|
||||||
export const name = "hashtag";
|
|
||||||
|
|
||||||
export const schema = {
|
|
||||||
"local.users": { uniqueIncrement: true },
|
|
||||||
"remote.users": { uniqueIncrement: true },
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const entity = Chart.schemaToEntity(name, schema, true);
|
|
|
@ -1,32 +0,0 @@
|
||||||
import Chart from "../../core.js";
|
|
||||||
|
|
||||||
export const name = "instance";
|
|
||||||
|
|
||||||
export const schema = {
|
|
||||||
"requests.failed": { range: "small" },
|
|
||||||
"requests.succeeded": { range: "small" },
|
|
||||||
"requests.received": { range: "small" },
|
|
||||||
"notes.total": { accumulate: true },
|
|
||||||
"notes.inc": {},
|
|
||||||
"notes.dec": {},
|
|
||||||
"notes.diffs.normal": {},
|
|
||||||
"notes.diffs.reply": {},
|
|
||||||
"notes.diffs.renote": {},
|
|
||||||
"notes.diffs.withFile": {},
|
|
||||||
"users.total": { accumulate: true },
|
|
||||||
"users.inc": { range: "small" },
|
|
||||||
"users.dec": { range: "small" },
|
|
||||||
"following.total": { accumulate: true },
|
|
||||||
"following.inc": { range: "small" },
|
|
||||||
"following.dec": { range: "small" },
|
|
||||||
"followers.total": { accumulate: true },
|
|
||||||
"followers.inc": { range: "small" },
|
|
||||||
"followers.dec": { range: "small" },
|
|
||||||
"drive.totalFiles": { accumulate: true },
|
|
||||||
"drive.incFiles": {},
|
|
||||||
"drive.decFiles": {},
|
|
||||||
"drive.incUsage": {}, // in kilobyte
|
|
||||||
"drive.decUsage": {}, // in kilobyte
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const entity = Chart.schemaToEntity(name, schema, true);
|
|
|
@ -1,22 +0,0 @@
|
||||||
import Chart from "../../core.js";
|
|
||||||
|
|
||||||
export const name = "notes";
|
|
||||||
|
|
||||||
export const schema = {
|
|
||||||
"local.total": { accumulate: true },
|
|
||||||
"local.inc": {},
|
|
||||||
"local.dec": {},
|
|
||||||
"local.diffs.normal": {},
|
|
||||||
"local.diffs.reply": {},
|
|
||||||
"local.diffs.renote": {},
|
|
||||||
"local.diffs.withFile": {},
|
|
||||||
"remote.total": { accumulate: true },
|
|
||||||
"remote.inc": {},
|
|
||||||
"remote.dec": {},
|
|
||||||
"remote.diffs.normal": {},
|
|
||||||
"remote.diffs.reply": {},
|
|
||||||
"remote.diffs.renote": {},
|
|
||||||
"remote.diffs.withFile": {},
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const entity = Chart.schemaToEntity(name, schema);
|
|
|
@ -1,14 +0,0 @@
|
||||||
import Chart from "../../core.js";
|
|
||||||
|
|
||||||
export const name = "perUserDrive";
|
|
||||||
|
|
||||||
export const schema = {
|
|
||||||
totalCount: { accumulate: true },
|
|
||||||
totalSize: { accumulate: true }, // in kilobyte
|
|
||||||
incCount: { range: "small" },
|
|
||||||
incSize: {}, // in kilobyte
|
|
||||||
decCount: { range: "small" },
|
|
||||||
decSize: {}, // in kilobyte
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const entity = Chart.schemaToEntity(name, schema, true);
|
|
|
@ -1,20 +0,0 @@
|
||||||
import Chart from "../../core.js";
|
|
||||||
|
|
||||||
export const name = "perUserFollowing";
|
|
||||||
|
|
||||||
export const schema = {
|
|
||||||
"local.followings.total": { accumulate: true },
|
|
||||||
"local.followings.inc": { range: "small" },
|
|
||||||
"local.followings.dec": { range: "small" },
|
|
||||||
"local.followers.total": { accumulate: true },
|
|
||||||
"local.followers.inc": { range: "small" },
|
|
||||||
"local.followers.dec": { range: "small" },
|
|
||||||
"remote.followings.total": { accumulate: true },
|
|
||||||
"remote.followings.inc": { range: "small" },
|
|
||||||
"remote.followings.dec": { range: "small" },
|
|
||||||
"remote.followers.total": { accumulate: true },
|
|
||||||
"remote.followers.inc": { range: "small" },
|
|
||||||
"remote.followers.dec": { range: "small" },
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const entity = Chart.schemaToEntity(name, schema, true);
|
|
|
@ -1,15 +0,0 @@
|
||||||
import Chart from "../../core.js";
|
|
||||||
|
|
||||||
export const name = "perUserNotes";
|
|
||||||
|
|
||||||
export const schema = {
|
|
||||||
total: { accumulate: true },
|
|
||||||
inc: { range: "small" },
|
|
||||||
dec: { range: "small" },
|
|
||||||
"diffs.normal": { range: "small" },
|
|
||||||
"diffs.reply": { range: "small" },
|
|
||||||
"diffs.renote": { range: "small" },
|
|
||||||
"diffs.withFile": { range: "small" },
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const entity = Chart.schemaToEntity(name, schema, true);
|
|
|
@ -1,10 +0,0 @@
|
||||||
import Chart from "../../core.js";
|
|
||||||
|
|
||||||
export const name = "perUserReaction";
|
|
||||||
|
|
||||||
export const schema = {
|
|
||||||
"local.count": { range: "small" },
|
|
||||||
"remote.count": { range: "small" },
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const entity = Chart.schemaToEntity(name, schema, true);
|
|
|
@ -1,11 +0,0 @@
|
||||||
import Chart from "../../core.js";
|
|
||||||
|
|
||||||
export const name = "testGrouped";
|
|
||||||
|
|
||||||
export const schema = {
|
|
||||||
"foo.total": { accumulate: true },
|
|
||||||
"foo.inc": {},
|
|
||||||
"foo.dec": {},
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const entity = Chart.schemaToEntity(name, schema, true);
|
|
|
@ -1,11 +0,0 @@
|
||||||
import Chart from "../../core.js";
|
|
||||||
|
|
||||||
export const name = "testIntersection";
|
|
||||||
|
|
||||||
export const schema = {
|
|
||||||
a: { uniqueIncrement: true },
|
|
||||||
b: { uniqueIncrement: true },
|
|
||||||
aAndB: { intersection: ["a", "b"] },
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const entity = Chart.schemaToEntity(name, schema);
|
|
|
@ -1,9 +0,0 @@
|
||||||
import Chart from "../../core.js";
|
|
||||||
|
|
||||||
export const name = "testUnique";
|
|
||||||
|
|
||||||
export const schema = {
|
|
||||||
foo: { uniqueIncrement: true },
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const entity = Chart.schemaToEntity(name, schema);
|
|
|
@ -1,11 +0,0 @@
|
||||||
import Chart from "../../core.js";
|
|
||||||
|
|
||||||
export const name = "test";
|
|
||||||
|
|
||||||
export const schema = {
|
|
||||||
"foo.total": { accumulate: true },
|
|
||||||
"foo.inc": {},
|
|
||||||
"foo.dec": {},
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const entity = Chart.schemaToEntity(name, schema);
|
|
|
@ -1,14 +0,0 @@
|
||||||
import Chart from "../../core.js";
|
|
||||||
|
|
||||||
export const name = "users";
|
|
||||||
|
|
||||||
export const schema = {
|
|
||||||
"local.total": { accumulate: true },
|
|
||||||
"local.inc": { range: "small" },
|
|
||||||
"local.dec": { range: "small" },
|
|
||||||
"remote.total": { accumulate: true },
|
|
||||||
"remote.inc": { range: "small" },
|
|
||||||
"remote.dec": { range: "small" },
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const entity = Chart.schemaToEntity(name, schema);
|
|
|
@ -1,142 +0,0 @@
|
||||||
import type { KVs } from "../core.js";
|
|
||||||
import Chart from "../core.js";
|
|
||||||
import { Followings, Instances } from "@/models/index.js";
|
|
||||||
import { name, schema } from "./entities/federation.js";
|
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* フェデレーションに関するチャート
|
|
||||||
*/
|
|
||||||
|
|
||||||
export default class FederationChart extends Chart<typeof schema> {
|
|
||||||
constructor() {
|
|
||||||
super(name, schema);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async tickMinor(): Promise<Partial<KVs<typeof schema>>> {
|
|
||||||
const meta = await fetchMeta();
|
|
||||||
|
|
||||||
const suspendedInstancesQuery = Instances.createQueryBuilder("instance")
|
|
||||||
.select("instance.host")
|
|
||||||
.where("instance.isSuspended = true");
|
|
||||||
|
|
||||||
const pubsubSubQuery = Followings.createQueryBuilder("f")
|
|
||||||
.select("f.followerHost")
|
|
||||||
.where("f.followerHost IS NOT NULL");
|
|
||||||
|
|
||||||
const subInstancesQuery = Followings.createQueryBuilder("f")
|
|
||||||
.select("f.followeeHost")
|
|
||||||
.where("f.followeeHost IS NOT NULL");
|
|
||||||
|
|
||||||
const pubInstancesQuery = Followings.createQueryBuilder("f")
|
|
||||||
.select("f.followerHost")
|
|
||||||
.where("f.followerHost IS NOT NULL");
|
|
||||||
|
|
||||||
const [sub, pub, pubsub, subActive, pubActive] = await Promise.all([
|
|
||||||
Followings.createQueryBuilder("following")
|
|
||||||
.select("COUNT(DISTINCT following.followeeHost)")
|
|
||||||
.where("following.followeeHost IS NOT NULL")
|
|
||||||
.andWhere(
|
|
||||||
meta.blockedHosts.length === 0
|
|
||||||
? "1=1"
|
|
||||||
: "following.followeeHost NOT IN (:...blocked)",
|
|
||||||
{ blocked: meta.blockedHosts },
|
|
||||||
)
|
|
||||||
.andWhere(
|
|
||||||
`following.followeeHost NOT IN (${suspendedInstancesQuery.getQuery()})`,
|
|
||||||
)
|
|
||||||
.getRawOne()
|
|
||||||
.then((x) => parseInt(x.count, 10)),
|
|
||||||
Followings.createQueryBuilder("following")
|
|
||||||
.select("COUNT(DISTINCT following.followerHost)")
|
|
||||||
.where("following.followerHost IS NOT NULL")
|
|
||||||
.andWhere(
|
|
||||||
meta.blockedHosts.length === 0
|
|
||||||
? "1=1"
|
|
||||||
: "following.followerHost NOT IN (:...blocked)",
|
|
||||||
{ blocked: meta.blockedHosts },
|
|
||||||
)
|
|
||||||
.andWhere(
|
|
||||||
`following.followerHost NOT IN (${suspendedInstancesQuery.getQuery()})`,
|
|
||||||
)
|
|
||||||
.getRawOne()
|
|
||||||
.then((x) => parseInt(x.count, 10)),
|
|
||||||
Followings.createQueryBuilder("following")
|
|
||||||
.select("COUNT(DISTINCT following.followeeHost)")
|
|
||||||
.where("following.followeeHost IS NOT NULL")
|
|
||||||
.andWhere(
|
|
||||||
meta.blockedHosts.length === 0
|
|
||||||
? "1=1"
|
|
||||||
: "following.followeeHost NOT IN (:...blocked)",
|
|
||||||
{ blocked: meta.blockedHosts },
|
|
||||||
)
|
|
||||||
.andWhere(
|
|
||||||
`following.followeeHost NOT IN (${suspendedInstancesQuery.getQuery()})`,
|
|
||||||
)
|
|
||||||
.andWhere(`following.followeeHost IN (${pubsubSubQuery.getQuery()})`)
|
|
||||||
.setParameters(pubsubSubQuery.getParameters())
|
|
||||||
.getRawOne()
|
|
||||||
.then((x) => parseInt(x.count, 10)),
|
|
||||||
Instances.createQueryBuilder("instance")
|
|
||||||
.select("COUNT(instance.id)")
|
|
||||||
.where(`instance.host IN (${subInstancesQuery.getQuery()})`)
|
|
||||||
.andWhere(
|
|
||||||
meta.blockedHosts.length === 0
|
|
||||||
? "1=1"
|
|
||||||
: "instance.host NOT IN (:...blocked)",
|
|
||||||
{ blocked: meta.blockedHosts },
|
|
||||||
)
|
|
||||||
.andWhere("instance.isSuspended = false")
|
|
||||||
.andWhere("instance.lastCommunicatedAt > :gt", {
|
|
||||||
gt: new Date(Date.now() - 1000 * 60 * 60 * 24 * 30),
|
|
||||||
})
|
|
||||||
.getRawOne()
|
|
||||||
.then((x) => parseInt(x.count, 10)),
|
|
||||||
Instances.createQueryBuilder("instance")
|
|
||||||
.select("COUNT(instance.id)")
|
|
||||||
.where(`instance.host IN (${pubInstancesQuery.getQuery()})`)
|
|
||||||
.andWhere(
|
|
||||||
meta.blockedHosts.length === 0
|
|
||||||
? "1=1"
|
|
||||||
: "instance.host NOT IN (:...blocked)",
|
|
||||||
{ blocked: meta.blockedHosts },
|
|
||||||
)
|
|
||||||
.andWhere("instance.isSuspended = false")
|
|
||||||
.andWhere("instance.lastCommunicatedAt > :gt", {
|
|
||||||
gt: new Date(Date.now() - 1000 * 60 * 60 * 24 * 30),
|
|
||||||
})
|
|
||||||
.getRawOne()
|
|
||||||
.then((x) => parseInt(x.count, 10)),
|
|
||||||
]);
|
|
||||||
|
|
||||||
return {
|
|
||||||
sub: sub,
|
|
||||||
pub: pub,
|
|
||||||
pubsub: pubsub,
|
|
||||||
subActive: subActive,
|
|
||||||
pubActive: pubActive,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public async deliverd(host: string, succeeded: boolean): Promise<void> {
|
|
||||||
await this.commit(
|
|
||||||
succeeded
|
|
||||||
? {
|
|
||||||
deliveredInstances: [host],
|
|
||||||
}
|
|
||||||
: {
|
|
||||||
stalled: [host],
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async inbox(host: string): Promise<void> {
|
|
||||||
await this.commit({
|
|
||||||
inboxInstances: [host],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
import type { KVs } from "../core.js";
|
|
||||||
import Chart from "../core.js";
|
|
||||||
import type { User } from "@/models/entities/user.js";
|
|
||||||
import { Users } from "@/models/index.js";
|
|
||||||
import { name, schema } from "./entities/hashtag.js";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ハッシュタグに関するチャート
|
|
||||||
*/
|
|
||||||
|
|
||||||
export default class HashtagChart extends Chart<typeof schema> {
|
|
||||||
constructor() {
|
|
||||||
super(name, schema, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async tickMinor(): Promise<Partial<KVs<typeof schema>>> {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
public async update(
|
|
||||||
hashtag: string,
|
|
||||||
user: { id: User["id"]; host: User["host"] },
|
|
||||||
): Promise<void> {
|
|
||||||
await this.commit(
|
|
||||||
{
|
|
||||||
"local.users": Users.isLocalUser(user) ? [user.id] : [],
|
|
||||||
"remote.users": Users.isLocalUser(user) ? [] : [user.id],
|
|
||||||
},
|
|
||||||
hashtag,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,142 +0,0 @@
|
||||||
import type { KVs } from "../core.js";
|
|
||||||
import Chart from "../core.js";
|
|
||||||
import { DriveFiles, Followings, Users, Notes } from "@/models/index.js";
|
|
||||||
import type { DriveFile } from "@/models/entities/drive-file.js";
|
|
||||||
import type { Note } from "@/models/entities/note.js";
|
|
||||||
import { toPuny } from "@/misc/convert-host.js";
|
|
||||||
import { name, schema } from "./entities/instance.js";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* インスタンスごとのチャート
|
|
||||||
*/
|
|
||||||
|
|
||||||
export default class InstanceChart extends Chart<typeof schema> {
|
|
||||||
constructor() {
|
|
||||||
super(name, schema, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async tickMajor(
|
|
||||||
group: string,
|
|
||||||
): Promise<Partial<KVs<typeof schema>>> {
|
|
||||||
const [notesCount, usersCount, followingCount, followersCount, driveFiles] =
|
|
||||||
await Promise.all([
|
|
||||||
Notes.countBy({ userHost: group }),
|
|
||||||
Users.countBy({ host: group }),
|
|
||||||
Followings.countBy({ followerHost: group }),
|
|
||||||
Followings.countBy({ followeeHost: group }),
|
|
||||||
DriveFiles.countBy({ userHost: group }),
|
|
||||||
]);
|
|
||||||
|
|
||||||
return {
|
|
||||||
"notes.total": notesCount,
|
|
||||||
"users.total": usersCount,
|
|
||||||
"following.total": followingCount,
|
|
||||||
"followers.total": followersCount,
|
|
||||||
"drive.totalFiles": driveFiles,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async tickMinor(): Promise<Partial<KVs<typeof schema>>> {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
public async requestReceived(host: string): Promise<void> {
|
|
||||||
await this.commit(
|
|
||||||
{
|
|
||||||
"requests.received": 1,
|
|
||||||
},
|
|
||||||
toPuny(host),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async requestSent(host: string, isSucceeded: boolean): Promise<void> {
|
|
||||||
await this.commit(
|
|
||||||
{
|
|
||||||
"requests.succeeded": isSucceeded ? 1 : 0,
|
|
||||||
"requests.failed": isSucceeded ? 0 : 1,
|
|
||||||
},
|
|
||||||
toPuny(host),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async newUser(host: string): Promise<void> {
|
|
||||||
await this.commit(
|
|
||||||
{
|
|
||||||
"users.total": 1,
|
|
||||||
"users.inc": 1,
|
|
||||||
},
|
|
||||||
toPuny(host),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async updateNote(
|
|
||||||
host: string,
|
|
||||||
note: Note,
|
|
||||||
isAdditional: boolean,
|
|
||||||
): Promise<void> {
|
|
||||||
await this.commit(
|
|
||||||
{
|
|
||||||
"notes.total": isAdditional ? 1 : -1,
|
|
||||||
"notes.inc": isAdditional ? 1 : 0,
|
|
||||||
"notes.dec": isAdditional ? 0 : 1,
|
|
||||||
"notes.diffs.normal":
|
|
||||||
note.replyId == null && note.renoteId == null
|
|
||||||
? isAdditional
|
|
||||||
? 1
|
|
||||||
: -1
|
|
||||||
: 0,
|
|
||||||
"notes.diffs.renote":
|
|
||||||
note.renoteId != null ? (isAdditional ? 1 : -1) : 0,
|
|
||||||
"notes.diffs.reply": note.replyId != null ? (isAdditional ? 1 : -1) : 0,
|
|
||||||
"notes.diffs.withFile":
|
|
||||||
note.fileIds.length > 0 ? (isAdditional ? 1 : -1) : 0,
|
|
||||||
},
|
|
||||||
toPuny(host),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async updateFollowing(
|
|
||||||
host: string,
|
|
||||||
isAdditional: boolean,
|
|
||||||
): Promise<void> {
|
|
||||||
await this.commit(
|
|
||||||
{
|
|
||||||
"following.total": isAdditional ? 1 : -1,
|
|
||||||
"following.inc": isAdditional ? 1 : 0,
|
|
||||||
"following.dec": isAdditional ? 0 : 1,
|
|
||||||
},
|
|
||||||
toPuny(host),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async updateFollowers(
|
|
||||||
host: string,
|
|
||||||
isAdditional: boolean,
|
|
||||||
): Promise<void> {
|
|
||||||
await this.commit(
|
|
||||||
{
|
|
||||||
"followers.total": isAdditional ? 1 : -1,
|
|
||||||
"followers.inc": isAdditional ? 1 : 0,
|
|
||||||
"followers.dec": isAdditional ? 0 : 1,
|
|
||||||
},
|
|
||||||
toPuny(host),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async updateDrive(
|
|
||||||
file: DriveFile,
|
|
||||||
isAdditional: boolean,
|
|
||||||
): Promise<void> {
|
|
||||||
const fileSizeKb = file.size / 1000;
|
|
||||||
await this.commit(
|
|
||||||
{
|
|
||||||
"drive.totalFiles": isAdditional ? 1 : -1,
|
|
||||||
"drive.incFiles": isAdditional ? 1 : 0,
|
|
||||||
"drive.incUsage": isAdditional ? fileSizeKb : 0,
|
|
||||||
"drive.decFiles": isAdditional ? 1 : 0,
|
|
||||||
"drive.decUsage": isAdditional ? fileSizeKb : 0,
|
|
||||||
},
|
|
||||||
file.userHost,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,58 +0,0 @@
|
||||||
import type { KVs } from "../core.js";
|
|
||||||
import Chart from "../core.js";
|
|
||||||
import { Notes } from "@/models/index.js";
|
|
||||||
import { Not, IsNull } from "typeorm";
|
|
||||||
import type { Note } from "@/models/entities/note.js";
|
|
||||||
import { name, schema } from "./entities/notes.js";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ノートに関するチャート
|
|
||||||
*/
|
|
||||||
|
|
||||||
export default class NotesChart extends Chart<typeof schema> {
|
|
||||||
constructor() {
|
|
||||||
super(name, schema);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
|
|
||||||
const [localCount, remoteCount] = await Promise.all([
|
|
||||||
Notes.countBy({ userHost: IsNull() }),
|
|
||||||
Notes.countBy({ userHost: Not(IsNull()) }),
|
|
||||||
]);
|
|
||||||
|
|
||||||
return {
|
|
||||||
"local.total": localCount,
|
|
||||||
"remote.total": remoteCount,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async tickMinor(): Promise<Partial<KVs<typeof schema>>> {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
public async update(
|
|
||||||
note: Note,
|
|
||||||
isAdditional: boolean,
|
|
||||||
byBot = false,
|
|
||||||
): Promise<void> {
|
|
||||||
const prefix = note.userHost === null ? "local" : "remote";
|
|
||||||
|
|
||||||
await this.commit({
|
|
||||||
[`${prefix}.total`]: isAdditional ? 1 : -1,
|
|
||||||
[`${prefix}.inc`]: isAdditional ? 1 : 0,
|
|
||||||
[`${prefix}.dec`]: isAdditional ? 0 : 1,
|
|
||||||
[`${prefix}.diffs.normal`]:
|
|
||||||
note.replyId == null && note.renoteId == null
|
|
||||||
? isAdditional
|
|
||||||
? 1
|
|
||||||
: -1
|
|
||||||
: 0,
|
|
||||||
[`${prefix}.diffs.renote`]:
|
|
||||||
note.renoteId != null && !byBot ? (isAdditional ? 1 : -1) : 0,
|
|
||||||
[`${prefix}.diffs.reply`]:
|
|
||||||
note.replyId != null ? (isAdditional ? 1 : -1) : 0,
|
|
||||||
[`${prefix}.diffs.withFile`]:
|
|
||||||
note.fileIds.length > 0 ? (isAdditional ? 1 : -1) : 0,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,48 +0,0 @@
|
||||||
import type { KVs } from "../core.js";
|
|
||||||
import Chart from "../core.js";
|
|
||||||
import { DriveFiles } from "@/models/index.js";
|
|
||||||
import type { DriveFile } from "@/models/entities/drive-file.js";
|
|
||||||
import { name, schema } from "./entities/per-user-drive.js";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ユーザーごとのドライブに関するチャート
|
|
||||||
*/
|
|
||||||
|
|
||||||
export default class PerUserDriveChart extends Chart<typeof schema> {
|
|
||||||
constructor() {
|
|
||||||
super(name, schema, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async tickMajor(
|
|
||||||
group: string,
|
|
||||||
): Promise<Partial<KVs<typeof schema>>> {
|
|
||||||
const [count, size] = await Promise.all([
|
|
||||||
DriveFiles.countBy({ userId: group }),
|
|
||||||
DriveFiles.calcDriveUsageOf(group),
|
|
||||||
]);
|
|
||||||
|
|
||||||
return {
|
|
||||||
totalCount: count,
|
|
||||||
totalSize: size,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async tickMinor(): Promise<Partial<KVs<typeof schema>>> {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
public async update(file: DriveFile, isAdditional: boolean): Promise<void> {
|
|
||||||
const fileSizeKb = file.size / 1000;
|
|
||||||
await this.commit(
|
|
||||||
{
|
|
||||||
totalCount: isAdditional ? 1 : -1,
|
|
||||||
totalSize: isAdditional ? fileSizeKb : -fileSizeKb,
|
|
||||||
incCount: isAdditional ? 1 : 0,
|
|
||||||
incSize: isAdditional ? fileSizeKb : 0,
|
|
||||||
decCount: isAdditional ? 0 : 1,
|
|
||||||
decSize: isAdditional ? 0 : fileSizeKb,
|
|
||||||
},
|
|
||||||
file.userId,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,69 +0,0 @@
|
||||||
import type { KVs } from "../core.js";
|
|
||||||
import Chart from "../core.js";
|
|
||||||
import { Followings, Users } from "@/models/index.js";
|
|
||||||
import { Not, IsNull } from "typeorm";
|
|
||||||
import type { User } from "@/models/entities/user.js";
|
|
||||||
import { name, schema } from "./entities/per-user-following.js";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ユーザーごとのフォローに関するチャート
|
|
||||||
*/
|
|
||||||
|
|
||||||
export default class PerUserFollowingChart extends Chart<typeof schema> {
|
|
||||||
constructor() {
|
|
||||||
super(name, schema, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async tickMajor(
|
|
||||||
group: string,
|
|
||||||
): Promise<Partial<KVs<typeof schema>>> {
|
|
||||||
const [
|
|
||||||
localFollowingsCount,
|
|
||||||
localFollowersCount,
|
|
||||||
remoteFollowingsCount,
|
|
||||||
remoteFollowersCount,
|
|
||||||
] = await Promise.all([
|
|
||||||
Followings.countBy({ followerId: group, followeeHost: IsNull() }),
|
|
||||||
Followings.countBy({ followeeId: group, followerHost: IsNull() }),
|
|
||||||
Followings.countBy({ followerId: group, followeeHost: Not(IsNull()) }),
|
|
||||||
Followings.countBy({ followeeId: group, followerHost: Not(IsNull()) }),
|
|
||||||
]);
|
|
||||||
|
|
||||||
return {
|
|
||||||
"local.followings.total": localFollowingsCount,
|
|
||||||
"local.followers.total": localFollowersCount,
|
|
||||||
"remote.followings.total": remoteFollowingsCount,
|
|
||||||
"remote.followers.total": remoteFollowersCount,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async tickMinor(): Promise<Partial<KVs<typeof schema>>> {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
public async update(
|
|
||||||
follower: { id: User["id"]; host: User["host"] },
|
|
||||||
followee: { id: User["id"]; host: User["host"] },
|
|
||||||
isFollow: boolean,
|
|
||||||
): Promise<void> {
|
|
||||||
const prefixFollower = Users.isLocalUser(follower) ? "local" : "remote";
|
|
||||||
const prefixFollowee = Users.isLocalUser(followee) ? "local" : "remote";
|
|
||||||
|
|
||||||
this.commit(
|
|
||||||
{
|
|
||||||
[`${prefixFollower}.followings.total`]: isFollow ? 1 : -1,
|
|
||||||
[`${prefixFollower}.followings.inc`]: isFollow ? 1 : 0,
|
|
||||||
[`${prefixFollower}.followings.dec`]: isFollow ? 0 : 1,
|
|
||||||
},
|
|
||||||
follower.id,
|
|
||||||
);
|
|
||||||
this.commit(
|
|
||||||
{
|
|
||||||
[`${prefixFollowee}.followers.total`]: isFollow ? 1 : -1,
|
|
||||||
[`${prefixFollowee}.followers.inc`]: isFollow ? 1 : 0,
|
|
||||||
[`${prefixFollowee}.followers.dec`]: isFollow ? 0 : 1,
|
|
||||||
},
|
|
||||||
followee.id,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
import type { KVs } from "../core.js";
|
|
||||||
import Chart from "../core.js";
|
|
||||||
import type { User } from "@/models/entities/user.js";
|
|
||||||
import { Notes } from "@/models/index.js";
|
|
||||||
import type { Note } from "@/models/entities/note.js";
|
|
||||||
import { name, schema } from "./entities/per-user-notes.js";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ユーザーごとのノートに関するチャート
|
|
||||||
*/
|
|
||||||
|
|
||||||
export default class PerUserNotesChart extends Chart<typeof schema> {
|
|
||||||
constructor() {
|
|
||||||
super(name, schema, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async tickMajor(
|
|
||||||
group: string,
|
|
||||||
): Promise<Partial<KVs<typeof schema>>> {
|
|
||||||
const [count] = await Promise.all([Notes.countBy({ userId: group })]);
|
|
||||||
|
|
||||||
return {
|
|
||||||
total: count,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async tickMinor(): Promise<Partial<KVs<typeof schema>>> {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
public async update(
|
|
||||||
user: { id: User["id"] },
|
|
||||||
note: Note,
|
|
||||||
isAdditional: boolean,
|
|
||||||
byBot = false,
|
|
||||||
): Promise<void> {
|
|
||||||
await this.commit(
|
|
||||||
{
|
|
||||||
total: isAdditional ? 1 : -1,
|
|
||||||
inc: isAdditional ? 1 : 0,
|
|
||||||
dec: isAdditional ? 0 : 1,
|
|
||||||
"diffs.normal":
|
|
||||||
note.replyId == null && note.renoteId == null
|
|
||||||
? isAdditional
|
|
||||||
? 1
|
|
||||||
: -1
|
|
||||||
: 0,
|
|
||||||
"diffs.renote":
|
|
||||||
note.renoteId != null && !byBot ? (isAdditional ? 1 : -1) : 0,
|
|
||||||
"diffs.reply": note.replyId != null ? (isAdditional ? 1 : -1) : 0,
|
|
||||||
"diffs.withFile": note.fileIds.length > 0 ? (isAdditional ? 1 : -1) : 0,
|
|
||||||
},
|
|
||||||
user.id,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
import type { KVs } from "../core.js";
|
|
||||||
import Chart from "../core.js";
|
|
||||||
import type { User } from "@/models/entities/user.js";
|
|
||||||
import type { Note } from "@/models/entities/note.js";
|
|
||||||
import { Users } from "@/models/index.js";
|
|
||||||
import { name, schema } from "./entities/per-user-reactions.js";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ユーザーごとのリアクションに関するチャート
|
|
||||||
*/
|
|
||||||
|
|
||||||
export default class PerUserReactionsChart extends Chart<typeof schema> {
|
|
||||||
constructor() {
|
|
||||||
super(name, schema, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async tickMajor(
|
|
||||||
group: string,
|
|
||||||
): Promise<Partial<KVs<typeof schema>>> {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async tickMinor(): Promise<Partial<KVs<typeof schema>>> {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
public async update(
|
|
||||||
user: { id: User["id"]; host: User["host"] },
|
|
||||||
note: Note,
|
|
||||||
): Promise<void> {
|
|
||||||
const prefix = Users.isLocalUser(user) ? "local" : "remote";
|
|
||||||
this.commit(
|
|
||||||
{
|
|
||||||
[`${prefix}.count`]: 1,
|
|
||||||
},
|
|
||||||
note.userId,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
import type { KVs } from "../core.js";
|
|
||||||
import Chart from "../core.js";
|
|
||||||
import { name, schema } from "./entities/test-grouped.js";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For testing
|
|
||||||
*/
|
|
||||||
|
|
||||||
export default class TestGroupedChart extends Chart<typeof schema> {
|
|
||||||
private total = {} as Record<string, number>;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super(name, schema, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async tickMajor(
|
|
||||||
group: string,
|
|
||||||
): Promise<Partial<KVs<typeof schema>>> {
|
|
||||||
return {
|
|
||||||
"foo.total": this.total[group],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async tickMinor(): Promise<Partial<KVs<typeof schema>>> {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
public async increment(group: string): Promise<void> {
|
|
||||||
if (this.total[group] == null) this.total[group] = 0;
|
|
||||||
|
|
||||||
this.total[group]++;
|
|
||||||
|
|
||||||
await this.commit(
|
|
||||||
{
|
|
||||||
"foo.total": 1,
|
|
||||||
"foo.inc": 1,
|
|
||||||
},
|
|
||||||
group,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
import type { KVs } from "../core.js";
|
|
||||||
import Chart from "../core.js";
|
|
||||||
import { name, schema } from "./entities/test-intersection.js";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For testing
|
|
||||||
*/
|
|
||||||
|
|
||||||
export default class TestIntersectionChart extends Chart<typeof schema> {
|
|
||||||
constructor() {
|
|
||||||
super(name, schema);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async tickMinor(): Promise<Partial<KVs<typeof schema>>> {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
public async addA(key: string): Promise<void> {
|
|
||||||
await this.commit({
|
|
||||||
a: [key],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public async addB(key: string): Promise<void> {
|
|
||||||
await this.commit({
|
|
||||||
b: [key],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
import type { KVs } from "../core.js";
|
|
||||||
import Chart from "../core.js";
|
|
||||||
import { name, schema } from "./entities/test-unique.js";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For testing
|
|
||||||
*/
|
|
||||||
|
|
||||||
export default class TestUniqueChart extends Chart<typeof schema> {
|
|
||||||
constructor() {
|
|
||||||
super(name, schema);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async tickMinor(): Promise<Partial<KVs<typeof schema>>> {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
public async uniqueIncrement(key: string): Promise<void> {
|
|
||||||
await this.commit({
|
|
||||||
foo: [key],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
import type { KVs } from "../core.js";
|
|
||||||
import Chart from "../core.js";
|
|
||||||
import { name, schema } from "./entities/test.js";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For testing
|
|
||||||
*/
|
|
||||||
|
|
||||||
export default class TestChart extends Chart<typeof schema> {
|
|
||||||
public total = 0; // publicにするのはテストのため
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super(name, schema);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
|
|
||||||
return {
|
|
||||||
"foo.total": this.total,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async tickMinor(): Promise<Partial<KVs<typeof schema>>> {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
public async increment(): Promise<void> {
|
|
||||||
this.total++;
|
|
||||||
|
|
||||||
await this.commit({
|
|
||||||
"foo.total": 1,
|
|
||||||
"foo.inc": 1,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public async decrement(): Promise<void> {
|
|
||||||
this.total--;
|
|
||||||
|
|
||||||
await this.commit({
|
|
||||||
"foo.total": -1,
|
|
||||||
"foo.dec": 1,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
import type { KVs } from "../core.js";
|
|
||||||
import Chart from "../core.js";
|
|
||||||
import { Users } from "@/models/index.js";
|
|
||||||
import { Not, IsNull } from "typeorm";
|
|
||||||
import type { User } from "@/models/entities/user.js";
|
|
||||||
import { name, schema } from "./entities/users.js";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ユーザー数に関するチャート
|
|
||||||
*/
|
|
||||||
|
|
||||||
export default class UsersChart extends Chart<typeof schema> {
|
|
||||||
constructor() {
|
|
||||||
super(name, schema);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
|
|
||||||
const [localCount, remoteCount] = await Promise.all([
|
|
||||||
Users.countBy({ host: IsNull() }),
|
|
||||||
Users.countBy({ host: Not(IsNull()) }),
|
|
||||||
]);
|
|
||||||
|
|
||||||
return {
|
|
||||||
"local.total": localCount,
|
|
||||||
"remote.total": remoteCount,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async tickMinor(): Promise<Partial<KVs<typeof schema>>> {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
public async update(
|
|
||||||
user: { id: User["id"]; host: User["host"] },
|
|
||||||
isAdditional: boolean,
|
|
||||||
): Promise<void> {
|
|
||||||
const prefix = Users.isLocalUser(user) ? "local" : "remote";
|
|
||||||
|
|
||||||
await this.commit({
|
|
||||||
[`${prefix}.total`]: isAdditional ? 1 : -1,
|
|
||||||
[`${prefix}.inc`]: isAdditional ? 1 : 0,
|
|
||||||
[`${prefix}.dec`]: isAdditional ? 0 : 1,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -163,16 +163,6 @@ export default abstract class Chart<T extends Schema> {
|
||||||
date: number;
|
date: number;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
/**
|
|
||||||
* 1日に一回程度実行されれば良いような計算処理を入れる(主にCASCADE削除などアプリケーション側で感知できない変動によるズレの修正用)
|
|
||||||
*/
|
|
||||||
protected abstract tickMajor(group: string | null): Promise<Partial<KVs<T>>>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 少なくとも最小スパン内に1回は実行されて欲しい計算処理を入れる
|
|
||||||
*/
|
|
||||||
protected abstract tickMinor(group: string | null): Promise<Partial<KVs<T>>>;
|
|
||||||
|
|
||||||
private static convertSchemaToColumnDefinitions(
|
private static convertSchemaToColumnDefinitions(
|
||||||
schema: Schema,
|
schema: Schema,
|
||||||
): Record<string, { type: string; array?: boolean; default?: any }> {
|
): Record<string, { type: string; array?: boolean; default?: any }> {
|
||||||
|
@ -680,58 +670,6 @@ export default abstract class Chart<T extends Schema> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async tick(
|
|
||||||
major: boolean,
|
|
||||||
group: string | null = null,
|
|
||||||
): Promise<void> {
|
|
||||||
const data = major
|
|
||||||
? await this.tickMajor(group)
|
|
||||||
: await this.tickMinor(group);
|
|
||||||
|
|
||||||
const columns = {} as Record<keyof Columns<T>, number>;
|
|
||||||
for (const [k, v] of Object.entries(data) as [
|
|
||||||
keyof typeof data,
|
|
||||||
number,
|
|
||||||
][]) {
|
|
||||||
const name = (columnPrefix +
|
|
||||||
(k as string).replaceAll(".", columnDot)) as keyof Columns<T>;
|
|
||||||
columns[name] = v;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Object.keys(columns).length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const update = async (
|
|
||||||
logHour: RawRecord<T>,
|
|
||||||
logDay: RawRecord<T>,
|
|
||||||
): Promise<void> => {
|
|
||||||
await Promise.all([
|
|
||||||
this.repositoryForHour
|
|
||||||
.createQueryBuilder()
|
|
||||||
.update()
|
|
||||||
.set(columns)
|
|
||||||
.where("id = :id", { id: logHour.id })
|
|
||||||
.execute(),
|
|
||||||
this.repositoryForDay
|
|
||||||
.createQueryBuilder()
|
|
||||||
.update()
|
|
||||||
.set(columns)
|
|
||||||
.where("id = :id", { id: logDay.id })
|
|
||||||
.execute(),
|
|
||||||
]);
|
|
||||||
};
|
|
||||||
|
|
||||||
return Promise.all([
|
|
||||||
this.claimCurrentLog(group, "hour"),
|
|
||||||
this.claimCurrentLog(group, "day"),
|
|
||||||
]).then(([logHour, logDay]) => update(logHour, logDay));
|
|
||||||
}
|
|
||||||
|
|
||||||
public resync(group: string | null = null): Promise<void> {
|
|
||||||
return this.tick(true, group);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async clean(): Promise<void> {
|
public async clean(): Promise<void> {
|
||||||
const current = dateUTC(Chart.getCurrentDate());
|
const current = dateUTC(Chart.getCurrentDate());
|
||||||
|
|
||||||
|
|
|
@ -1,57 +1,3 @@
|
||||||
import { entity as FederationChart } from "./charts/entities/federation.js";
|
|
||||||
import { entity as NotesChart } from "./charts/entities/notes.js";
|
|
||||||
import { entity as UsersChart } from "./charts/entities/users.js";
|
|
||||||
import { entity as ActiveUsersChart } from "./charts/entities/active-users.js";
|
import { entity as ActiveUsersChart } from "./charts/entities/active-users.js";
|
||||||
import { entity as InstanceChart } from "./charts/entities/instance.js";
|
|
||||||
import { entity as PerUserNotesChart } from "./charts/entities/per-user-notes.js";
|
|
||||||
import { entity as DriveChart } from "./charts/entities/drive.js";
|
|
||||||
import { entity as PerUserReactionsChart } from "./charts/entities/per-user-reactions.js";
|
|
||||||
import { entity as HashtagChart } from "./charts/entities/hashtag.js";
|
|
||||||
import { entity as PerUserFollowingChart } from "./charts/entities/per-user-following.js";
|
|
||||||
import { entity as PerUserDriveChart } from "./charts/entities/per-user-drive.js";
|
|
||||||
import { entity as ApRequestChart } from "./charts/entities/ap-request.js";
|
|
||||||
|
|
||||||
import { entity as TestChart } from "./charts/entities/test.js";
|
export const entities = [ActiveUsersChart.hour, ActiveUsersChart.day];
|
||||||
import { entity as TestGroupedChart } from "./charts/entities/test-grouped.js";
|
|
||||||
import { entity as TestUniqueChart } from "./charts/entities/test-unique.js";
|
|
||||||
import { entity as TestIntersectionChart } from "./charts/entities/test-intersection.js";
|
|
||||||
|
|
||||||
export const entities = [
|
|
||||||
FederationChart.hour,
|
|
||||||
FederationChart.day,
|
|
||||||
NotesChart.hour,
|
|
||||||
NotesChart.day,
|
|
||||||
UsersChart.hour,
|
|
||||||
UsersChart.day,
|
|
||||||
ActiveUsersChart.hour,
|
|
||||||
ActiveUsersChart.day,
|
|
||||||
InstanceChart.hour,
|
|
||||||
InstanceChart.day,
|
|
||||||
PerUserNotesChart.hour,
|
|
||||||
PerUserNotesChart.day,
|
|
||||||
DriveChart.hour,
|
|
||||||
DriveChart.day,
|
|
||||||
PerUserReactionsChart.hour,
|
|
||||||
PerUserReactionsChart.day,
|
|
||||||
HashtagChart.hour,
|
|
||||||
HashtagChart.day,
|
|
||||||
PerUserFollowingChart.hour,
|
|
||||||
PerUserFollowingChart.day,
|
|
||||||
PerUserDriveChart.hour,
|
|
||||||
PerUserDriveChart.day,
|
|
||||||
ApRequestChart.hour,
|
|
||||||
ApRequestChart.day,
|
|
||||||
|
|
||||||
...(process.env.NODE_ENV === "test"
|
|
||||||
? [
|
|
||||||
TestChart.hour,
|
|
||||||
TestChart.day,
|
|
||||||
TestGroupedChart.hour,
|
|
||||||
TestGroupedChart.day,
|
|
||||||
TestUniqueChart.hour,
|
|
||||||
TestUniqueChart.day,
|
|
||||||
TestIntersectionChart.hour,
|
|
||||||
TestIntersectionChart.day,
|
|
||||||
]
|
|
||||||
: []),
|
|
||||||
];
|
|
||||||
|
|
|
@ -1,54 +1,7 @@
|
||||||
import { beforeShutdown } from "@/misc/before-shutdown.js";
|
import { beforeShutdown } from "@/misc/before-shutdown.js";
|
||||||
|
|
||||||
import FederationChart from "./charts/federation.js";
|
|
||||||
import NotesChart from "./charts/notes.js";
|
|
||||||
import UsersChart from "./charts/users.js";
|
|
||||||
import ActiveUsersChart from "./charts/active-users.js";
|
import ActiveUsersChart from "./charts/active-users.js";
|
||||||
import InstanceChart from "./charts/instance.js";
|
|
||||||
import PerUserNotesChart from "./charts/per-user-notes.js";
|
|
||||||
import DriveChart from "./charts/drive.js";
|
|
||||||
import PerUserReactionsChart from "./charts/per-user-reactions.js";
|
|
||||||
import HashtagChart from "./charts/hashtag.js";
|
|
||||||
import PerUserFollowingChart from "./charts/per-user-following.js";
|
|
||||||
import PerUserDriveChart from "./charts/per-user-drive.js";
|
|
||||||
import ApRequestChart from "./charts/ap-request.js";
|
|
||||||
|
|
||||||
export const federationChart = new FederationChart();
|
|
||||||
export const notesChart = new NotesChart();
|
|
||||||
export const usersChart = new UsersChart();
|
|
||||||
export const activeUsersChart = new ActiveUsersChart();
|
export const activeUsersChart = new ActiveUsersChart();
|
||||||
export const instanceChart = new InstanceChart();
|
|
||||||
export const perUserNotesChart = new PerUserNotesChart();
|
|
||||||
export const driveChart = new DriveChart();
|
|
||||||
export const perUserReactionsChart = new PerUserReactionsChart();
|
|
||||||
export const hashtagChart = new HashtagChart();
|
|
||||||
export const perUserFollowingChart = new PerUserFollowingChart();
|
|
||||||
export const perUserDriveChart = new PerUserDriveChart();
|
|
||||||
export const apRequestChart = new ApRequestChart();
|
|
||||||
|
|
||||||
const charts = [
|
setInterval(() => activeUsersChart.save(), 1000 * 60 * 20);
|
||||||
federationChart,
|
beforeShutdown(() => activeUsersChart.save());
|
||||||
notesChart,
|
|
||||||
usersChart,
|
|
||||||
activeUsersChart,
|
|
||||||
instanceChart,
|
|
||||||
perUserNotesChart,
|
|
||||||
driveChart,
|
|
||||||
perUserReactionsChart,
|
|
||||||
hashtagChart,
|
|
||||||
perUserFollowingChart,
|
|
||||||
perUserDriveChart,
|
|
||||||
apRequestChart,
|
|
||||||
];
|
|
||||||
|
|
||||||
// 20分おきにメモリ情報をDBに書き込み
|
|
||||||
setInterval(
|
|
||||||
() => {
|
|
||||||
for (const chart of charts) {
|
|
||||||
chart.save();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
1000 * 60 * 20,
|
|
||||||
);
|
|
||||||
|
|
||||||
beforeShutdown(() => Promise.all(charts.map((chart) => chart.save())));
|
|
||||||
|
|
|
@ -17,11 +17,6 @@ import {
|
||||||
} from "@/models/index.js";
|
} from "@/models/index.js";
|
||||||
import { DriveFile } from "@/models/entities/drive-file.js";
|
import { DriveFile } from "@/models/entities/drive-file.js";
|
||||||
import type { IRemoteUser, User } from "@/models/entities/user.js";
|
import type { IRemoteUser, User } from "@/models/entities/user.js";
|
||||||
import {
|
|
||||||
driveChart,
|
|
||||||
perUserDriveChart,
|
|
||||||
instanceChart,
|
|
||||||
} from "@/services/chart/index.js";
|
|
||||||
import { genId } from "@/misc/gen-id.js";
|
import { genId } from "@/misc/gen-id.js";
|
||||||
import { isDuplicateKeyValueError } from "@/misc/is-duplicate-key-value-error.js";
|
import { isDuplicateKeyValueError } from "@/misc/is-duplicate-key-value-error.js";
|
||||||
import { FILE_TYPE_BROWSERSAFE } from "@/const.js";
|
import { FILE_TYPE_BROWSERSAFE } from "@/const.js";
|
||||||
|
@ -655,12 +650,5 @@ export async function addFile({
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 統計を更新
|
|
||||||
driveChart.update(file, true);
|
|
||||||
perUserDriveChart.update(file, true);
|
|
||||||
if (file.userHost !== null) {
|
|
||||||
instanceChart.updateDrive(file, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,6 @@
|
||||||
import type { DriveFile } from "@/models/entities/drive-file.js";
|
import type { DriveFile } from "@/models/entities/drive-file.js";
|
||||||
import { InternalStorage } from "./internal-storage.js";
|
import { InternalStorage } from "./internal-storage.js";
|
||||||
import { DriveFiles } from "@/models/index.js";
|
import { DriveFiles } from "@/models/index.js";
|
||||||
import {
|
|
||||||
driveChart,
|
|
||||||
perUserDriveChart,
|
|
||||||
instanceChart,
|
|
||||||
} from "@/services/chart/index.js";
|
|
||||||
import { createDeleteObjectStorageFileJob } from "@/queue/index.js";
|
import { createDeleteObjectStorageFileJob } from "@/queue/index.js";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||||
import { getS3 } from "./s3.js";
|
import { getS3 } from "./s3.js";
|
||||||
|
@ -84,13 +79,6 @@ async function postProcess(file: DriveFile, isExpired = false) {
|
||||||
} else {
|
} else {
|
||||||
DriveFiles.delete(file.id);
|
DriveFiles.delete(file.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 統計を更新
|
|
||||||
driveChart.update(file, false);
|
|
||||||
perUserDriveChart.update(file, false);
|
|
||||||
if (file.userHost != null) {
|
|
||||||
instanceChart.updateDrive(file, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function deleteObjectStorageFile(key: string) {
|
export async function deleteObjectStorageFile(key: string) {
|
||||||
|
|
|
@ -17,10 +17,6 @@ import {
|
||||||
Instances,
|
Instances,
|
||||||
UserProfiles,
|
UserProfiles,
|
||||||
} from "@/models/index.js";
|
} from "@/models/index.js";
|
||||||
import {
|
|
||||||
instanceChart,
|
|
||||||
perUserFollowingChart,
|
|
||||||
} from "@/services/chart/index.js";
|
|
||||||
import { genId } from "@/misc/gen-id.js";
|
import { genId } from "@/misc/gen-id.js";
|
||||||
import { createNotification } from "@/services/create-notification.js";
|
import { createNotification } from "@/services/create-notification.js";
|
||||||
import { isDuplicateKeyValueError } from "@/misc/is-duplicate-key-value-error.js";
|
import { isDuplicateKeyValueError } from "@/misc/is-duplicate-key-value-error.js";
|
||||||
|
@ -111,18 +107,14 @@ export async function insertFollowingDoc(
|
||||||
if (Users.isRemoteUser(follower) && Users.isLocalUser(followee)) {
|
if (Users.isRemoteUser(follower) && Users.isLocalUser(followee)) {
|
||||||
registerOrFetchInstanceDoc(follower.host).then((i) => {
|
registerOrFetchInstanceDoc(follower.host).then((i) => {
|
||||||
Instances.increment({ id: i.id }, "followingCount", 1);
|
Instances.increment({ id: i.id }, "followingCount", 1);
|
||||||
instanceChart.updateFollowing(i.host, true);
|
|
||||||
});
|
});
|
||||||
} else if (Users.isLocalUser(follower) && Users.isRemoteUser(followee)) {
|
} else if (Users.isLocalUser(follower) && Users.isRemoteUser(followee)) {
|
||||||
registerOrFetchInstanceDoc(followee.host).then((i) => {
|
registerOrFetchInstanceDoc(followee.host).then((i) => {
|
||||||
Instances.increment({ id: i.id }, "followersCount", 1);
|
Instances.increment({ id: i.id }, "followersCount", 1);
|
||||||
instanceChart.updateFollowers(i.host, true);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
perUserFollowingChart.update(follower, followee, true);
|
|
||||||
|
|
||||||
// Publish follow event
|
// Publish follow event
|
||||||
if (Users.isLocalUser(follower)) {
|
if (Users.isLocalUser(follower)) {
|
||||||
Users.pack(followee.id, follower, {
|
Users.pack(followee.id, follower, {
|
||||||
|
|
|
@ -8,10 +8,6 @@ import Logger from "../logger.js";
|
||||||
import { registerOrFetchInstanceDoc } from "@/services/register-or-fetch-instance-doc.js";
|
import { registerOrFetchInstanceDoc } from "@/services/register-or-fetch-instance-doc.js";
|
||||||
import type { User } from "@/models/entities/user.js";
|
import type { User } from "@/models/entities/user.js";
|
||||||
import { Followings, Users, Instances } from "@/models/index.js";
|
import { Followings, Users, Instances } from "@/models/index.js";
|
||||||
import {
|
|
||||||
instanceChart,
|
|
||||||
perUserFollowingChart,
|
|
||||||
} from "@/services/chart/index.js";
|
|
||||||
import { getActiveWebhooks } from "@/misc/webhook-cache.js";
|
import { getActiveWebhooks } from "@/misc/webhook-cache.js";
|
||||||
|
|
||||||
const logger = new Logger("following/delete");
|
const logger = new Logger("following/delete");
|
||||||
|
@ -99,15 +95,11 @@ export async function decrementFollowing(
|
||||||
if (Users.isRemoteUser(follower) && Users.isLocalUser(followee)) {
|
if (Users.isRemoteUser(follower) && Users.isLocalUser(followee)) {
|
||||||
registerOrFetchInstanceDoc(follower.host).then((i) => {
|
registerOrFetchInstanceDoc(follower.host).then((i) => {
|
||||||
Instances.decrement({ id: i.id }, "followingCount", 1);
|
Instances.decrement({ id: i.id }, "followingCount", 1);
|
||||||
instanceChart.updateFollowing(i.host, false);
|
|
||||||
});
|
});
|
||||||
} else if (Users.isLocalUser(follower) && Users.isRemoteUser(followee)) {
|
} else if (Users.isLocalUser(follower) && Users.isRemoteUser(followee)) {
|
||||||
registerOrFetchInstanceDoc(followee.host).then((i) => {
|
registerOrFetchInstanceDoc(followee.host).then((i) => {
|
||||||
Instances.decrement({ id: i.id }, "followersCount", 1);
|
Instances.decrement({ id: i.id }, "followersCount", 1);
|
||||||
instanceChart.updateFollowers(i.host, false);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
perUserFollowingChart.update(follower, followee, false);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,12 +39,7 @@ import type { App } from "@/models/entities/app.js";
|
||||||
import { Not, In } from "typeorm";
|
import { Not, In } from "typeorm";
|
||||||
import type { User, ILocalUser, IRemoteUser } from "@/models/entities/user.js";
|
import type { User, ILocalUser, IRemoteUser } from "@/models/entities/user.js";
|
||||||
import { genId } from "@/misc/gen-id.js";
|
import { genId } from "@/misc/gen-id.js";
|
||||||
import {
|
import { activeUsersChart } from "@/services/chart/index.js";
|
||||||
notesChart,
|
|
||||||
perUserNotesChart,
|
|
||||||
activeUsersChart,
|
|
||||||
instanceChart,
|
|
||||||
} from "@/services/chart/index.js";
|
|
||||||
import type { IPoll } from "@/models/entities/poll.js";
|
import type { IPoll } from "@/models/entities/poll.js";
|
||||||
import { Poll } from "@/models/entities/poll.js";
|
import { Poll } from "@/models/entities/poll.js";
|
||||||
import { createNotification } from "@/services/create-notification.js";
|
import { createNotification } from "@/services/create-notification.js";
|
||||||
|
@ -350,15 +345,10 @@ export default async (
|
||||||
|
|
||||||
res(note);
|
res(note);
|
||||||
|
|
||||||
// 統計を更新
|
|
||||||
notesChart.update(note, true, user.isBot);
|
|
||||||
perUserNotesChart.update(user, note, true, user.isBot);
|
|
||||||
|
|
||||||
// Register host
|
// Register host
|
||||||
if (Users.isRemoteUser(user)) {
|
if (Users.isRemoteUser(user)) {
|
||||||
registerOrFetchInstanceDoc(user.host).then((i) => {
|
registerOrFetchInstanceDoc(user.host).then((i) => {
|
||||||
Instances.increment({ id: i.id }, "notesCount", 1);
|
Instances.increment({ id: i.id }, "notesCount", 1);
|
||||||
instanceChart.updateNote(i.host, note, true);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,11 +9,6 @@ import config from "@/config/index.js";
|
||||||
import type { User, ILocalUser, IRemoteUser } from "@/models/entities/user.js";
|
import type { User, ILocalUser, IRemoteUser } from "@/models/entities/user.js";
|
||||||
import type { Note, IMentionedRemoteUsers } from "@/models/entities/note.js";
|
import type { Note, IMentionedRemoteUsers } from "@/models/entities/note.js";
|
||||||
import { Notes, Users, Instances } from "@/models/index.js";
|
import { Notes, Users, Instances } from "@/models/index.js";
|
||||||
import {
|
|
||||||
notesChart,
|
|
||||||
perUserNotesChart,
|
|
||||||
instanceChart,
|
|
||||||
} from "@/services/chart/index.js";
|
|
||||||
import {
|
import {
|
||||||
deliverToFollowers,
|
deliverToFollowers,
|
||||||
deliverToUser,
|
deliverToUser,
|
||||||
|
@ -109,14 +104,9 @@ export default async function (
|
||||||
}
|
}
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
// 統計を更新
|
|
||||||
notesChart.update(note, false);
|
|
||||||
perUserNotesChart.update(user, note, false);
|
|
||||||
|
|
||||||
if (Users.isRemoteUser(user)) {
|
if (Users.isRemoteUser(user)) {
|
||||||
registerOrFetchInstanceDoc(user.host).then((i) => {
|
registerOrFetchInstanceDoc(user.host).then((i) => {
|
||||||
Instances.decrement({ id: i.id }, "notesCount", 1);
|
Instances.decrement({ id: i.id }, "notesCount", 1);
|
||||||
instanceChart.updateNote(i.host, note, false);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,6 @@ import {
|
||||||
Blockings,
|
Blockings,
|
||||||
} from "@/models/index.js";
|
} from "@/models/index.js";
|
||||||
import { IsNull, Not } from "typeorm";
|
import { IsNull, Not } from "typeorm";
|
||||||
import { perUserReactionsChart } from "@/services/chart/index.js";
|
|
||||||
import { genId } from "@/misc/gen-id.js";
|
import { genId } from "@/misc/gen-id.js";
|
||||||
import { createNotification } from "@/services/create-notification.js";
|
import { createNotification } from "@/services/create-notification.js";
|
||||||
import deleteReaction from "./delete.js";
|
import deleteReaction from "./delete.js";
|
||||||
|
@ -91,8 +90,6 @@ export default async (
|
||||||
.where("id = :id", { id: note.id })
|
.where("id = :id", { id: note.id })
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
perUserReactionsChart.update(user, note);
|
|
||||||
|
|
||||||
// カスタム絵文字リアクションだったら絵文字情報も送る
|
// カスタム絵文字リアクションだったら絵文字情報も送る
|
||||||
const decodedReaction = decodeReaction(reaction);
|
const decodedReaction = decodeReaction(reaction);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import type { User } from "@/models/entities/user.js";
|
import type { User } from "@/models/entities/user.js";
|
||||||
import { Hashtags, Users } from "@/models/index.js";
|
import { Hashtags, Users } from "@/models/index.js";
|
||||||
import { hashtagChart } from "@/services/chart/index.js";
|
|
||||||
import { genId } from "@/misc/gen-id.js";
|
import { genId } from "@/misc/gen-id.js";
|
||||||
import type { Hashtag } from "@/models/entities/hashtag.js";
|
import type { Hashtag } from "@/models/entities/hashtag.js";
|
||||||
import { normalizeForSearch } from "@/misc/normalize-for-search.js";
|
import { normalizeForSearch } from "@/misc/normalize-for-search.js";
|
||||||
|
@ -151,8 +150,4 @@ export async function updateHashtag(
|
||||||
} as Hashtag);
|
} as Hashtag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isUserAttached) {
|
|
||||||
hashtagChart.update(tag, user);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,575 +0,0 @@
|
||||||
process.env.NODE_ENV = "test";
|
|
||||||
|
|
||||||
import * as assert from "assert";
|
|
||||||
import * as lolex from "@sinonjs/fake-timers";
|
|
||||||
import { initDb } from "../src/db/postgre.js";
|
|
||||||
import TestGroupedChart from "../src/services/chart/charts/test-grouped.js";
|
|
||||||
import TestIntersectionChart from "../src/services/chart/charts/test-intersection.js";
|
|
||||||
import TestUniqueChart from "../src/services/chart/charts/test-unique.js";
|
|
||||||
import TestChart from "../src/services/chart/charts/test.js";
|
|
||||||
|
|
||||||
describe("Chart", () => {
|
|
||||||
let testChart: TestChart;
|
|
||||||
let testGroupedChart: TestGroupedChart;
|
|
||||||
let testUniqueChart: TestUniqueChart;
|
|
||||||
let testIntersectionChart: TestIntersectionChart;
|
|
||||||
let clock: lolex.InstalledClock;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
await initDb(true);
|
|
||||||
|
|
||||||
testChart = new TestChart();
|
|
||||||
testGroupedChart = new TestGroupedChart();
|
|
||||||
testUniqueChart = new TestUniqueChart();
|
|
||||||
testIntersectionChart = new TestIntersectionChart();
|
|
||||||
|
|
||||||
clock = lolex.install({
|
|
||||||
now: new Date(Date.UTC(2000, 0, 1, 0, 0, 0)),
|
|
||||||
shouldClearNativeTimers: true,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
clock.uninstall();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Can updates", async () => {
|
|
||||||
await testChart.increment();
|
|
||||||
await testChart.save();
|
|
||||||
|
|
||||||
const chartHours = await testChart.getChart("hour", 3, null);
|
|
||||||
const chartDays = await testChart.getChart("day", 3, null);
|
|
||||||
|
|
||||||
assert.deepStrictEqual(chartHours, {
|
|
||||||
foo: {
|
|
||||||
dec: [0, 0, 0],
|
|
||||||
inc: [1, 0, 0],
|
|
||||||
total: [1, 0, 0],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.deepStrictEqual(chartDays, {
|
|
||||||
foo: {
|
|
||||||
dec: [0, 0, 0],
|
|
||||||
inc: [1, 0, 0],
|
|
||||||
total: [1, 0, 0],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Can updates (dec)", async () => {
|
|
||||||
await testChart.decrement();
|
|
||||||
await testChart.save();
|
|
||||||
|
|
||||||
const chartHours = await testChart.getChart("hour", 3, null);
|
|
||||||
const chartDays = await testChart.getChart("day", 3, null);
|
|
||||||
|
|
||||||
assert.deepStrictEqual(chartHours, {
|
|
||||||
foo: {
|
|
||||||
dec: [1, 0, 0],
|
|
||||||
inc: [0, 0, 0],
|
|
||||||
total: [-1, 0, 0],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.deepStrictEqual(chartDays, {
|
|
||||||
foo: {
|
|
||||||
dec: [1, 0, 0],
|
|
||||||
inc: [0, 0, 0],
|
|
||||||
total: [-1, 0, 0],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Empty chart", async () => {
|
|
||||||
const chartHours = await testChart.getChart("hour", 3, null);
|
|
||||||
const chartDays = await testChart.getChart("day", 3, null);
|
|
||||||
|
|
||||||
assert.deepStrictEqual(chartHours, {
|
|
||||||
foo: {
|
|
||||||
dec: [0, 0, 0],
|
|
||||||
inc: [0, 0, 0],
|
|
||||||
total: [0, 0, 0],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.deepStrictEqual(chartDays, {
|
|
||||||
foo: {
|
|
||||||
dec: [0, 0, 0],
|
|
||||||
inc: [0, 0, 0],
|
|
||||||
total: [0, 0, 0],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Can updates at multiple times at same time", async () => {
|
|
||||||
await testChart.increment();
|
|
||||||
await testChart.increment();
|
|
||||||
await testChart.increment();
|
|
||||||
await testChart.save();
|
|
||||||
|
|
||||||
const chartHours = await testChart.getChart("hour", 3, null);
|
|
||||||
const chartDays = await testChart.getChart("day", 3, null);
|
|
||||||
|
|
||||||
assert.deepStrictEqual(chartHours, {
|
|
||||||
foo: {
|
|
||||||
dec: [0, 0, 0],
|
|
||||||
inc: [3, 0, 0],
|
|
||||||
total: [3, 0, 0],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.deepStrictEqual(chartDays, {
|
|
||||||
foo: {
|
|
||||||
dec: [0, 0, 0],
|
|
||||||
inc: [3, 0, 0],
|
|
||||||
total: [3, 0, 0],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("複数回saveされてもデータの更新は一度だけ", async () => {
|
|
||||||
await testChart.increment();
|
|
||||||
await testChart.save();
|
|
||||||
await testChart.save();
|
|
||||||
await testChart.save();
|
|
||||||
|
|
||||||
const chartHours = await testChart.getChart("hour", 3, null);
|
|
||||||
const chartDays = await testChart.getChart("day", 3, null);
|
|
||||||
|
|
||||||
assert.deepStrictEqual(chartHours, {
|
|
||||||
foo: {
|
|
||||||
dec: [0, 0, 0],
|
|
||||||
inc: [1, 0, 0],
|
|
||||||
total: [1, 0, 0],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.deepStrictEqual(chartDays, {
|
|
||||||
foo: {
|
|
||||||
dec: [0, 0, 0],
|
|
||||||
inc: [1, 0, 0],
|
|
||||||
total: [1, 0, 0],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Can updates at different times", async () => {
|
|
||||||
await testChart.increment();
|
|
||||||
await testChart.save();
|
|
||||||
|
|
||||||
clock.tick("01:00:00");
|
|
||||||
|
|
||||||
await testChart.increment();
|
|
||||||
await testChart.save();
|
|
||||||
|
|
||||||
const chartHours = await testChart.getChart("hour", 3, null);
|
|
||||||
const chartDays = await testChart.getChart("day", 3, null);
|
|
||||||
|
|
||||||
assert.deepStrictEqual(chartHours, {
|
|
||||||
foo: {
|
|
||||||
dec: [0, 0, 0],
|
|
||||||
inc: [1, 1, 0],
|
|
||||||
total: [2, 1, 0],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.deepStrictEqual(chartDays, {
|
|
||||||
foo: {
|
|
||||||
dec: [0, 0, 0],
|
|
||||||
inc: [2, 0, 0],
|
|
||||||
total: [2, 0, 0],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// 仕様上はこうなってほしいけど、実装は難しそうなのでskip
|
|
||||||
/*
|
|
||||||
it('Can updates at different times without save', async () => {
|
|
||||||
await testChart.increment();
|
|
||||||
|
|
||||||
clock.tick('01:00:00');
|
|
||||||
|
|
||||||
await testChart.increment();
|
|
||||||
await testChart.save();
|
|
||||||
|
|
||||||
const chartHours = await testChart.getChart('hour', 3, null);
|
|
||||||
const chartDays = await testChart.getChart('day', 3, null);
|
|
||||||
|
|
||||||
assert.deepStrictEqual(chartHours, {
|
|
||||||
foo: {
|
|
||||||
dec: [0, 0, 0],
|
|
||||||
inc: [1, 1, 0],
|
|
||||||
total: [2, 1, 0]
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.deepStrictEqual(chartDays, {
|
|
||||||
foo: {
|
|
||||||
dec: [0, 0, 0],
|
|
||||||
inc: [2, 0, 0],
|
|
||||||
total: [2, 0, 0]
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
|
|
||||||
it("Can padding", async () => {
|
|
||||||
await testChart.increment();
|
|
||||||
await testChart.save();
|
|
||||||
|
|
||||||
clock.tick("02:00:00");
|
|
||||||
|
|
||||||
await testChart.increment();
|
|
||||||
await testChart.save();
|
|
||||||
|
|
||||||
const chartHours = await testChart.getChart("hour", 3, null);
|
|
||||||
const chartDays = await testChart.getChart("day", 3, null);
|
|
||||||
|
|
||||||
assert.deepStrictEqual(chartHours, {
|
|
||||||
foo: {
|
|
||||||
dec: [0, 0, 0],
|
|
||||||
inc: [1, 0, 1],
|
|
||||||
total: [2, 1, 1],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.deepStrictEqual(chartDays, {
|
|
||||||
foo: {
|
|
||||||
dec: [0, 0, 0],
|
|
||||||
inc: [2, 0, 0],
|
|
||||||
total: [2, 0, 0],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// 要求された範囲にログがひとつもない場合でもパディングできる
|
|
||||||
it("Can padding from past range", async () => {
|
|
||||||
await testChart.increment();
|
|
||||||
await testChart.save();
|
|
||||||
|
|
||||||
clock.tick("05:00:00");
|
|
||||||
|
|
||||||
const chartHours = await testChart.getChart("hour", 3, null);
|
|
||||||
const chartDays = await testChart.getChart("day", 3, null);
|
|
||||||
|
|
||||||
assert.deepStrictEqual(chartHours, {
|
|
||||||
foo: {
|
|
||||||
dec: [0, 0, 0],
|
|
||||||
inc: [0, 0, 0],
|
|
||||||
total: [1, 1, 1],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.deepStrictEqual(chartDays, {
|
|
||||||
foo: {
|
|
||||||
dec: [0, 0, 0],
|
|
||||||
inc: [1, 0, 0],
|
|
||||||
total: [1, 0, 0],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// 要求された範囲の最も古い箇所に位置するログが存在しない場合でもパディングできる
|
|
||||||
// Issue #3190
|
|
||||||
it("Can padding from past range 2", async () => {
|
|
||||||
await testChart.increment();
|
|
||||||
await testChart.save();
|
|
||||||
|
|
||||||
clock.tick("05:00:00");
|
|
||||||
|
|
||||||
await testChart.increment();
|
|
||||||
await testChart.save();
|
|
||||||
|
|
||||||
const chartHours = await testChart.getChart("hour", 3, null);
|
|
||||||
const chartDays = await testChart.getChart("day", 3, null);
|
|
||||||
|
|
||||||
assert.deepStrictEqual(chartHours, {
|
|
||||||
foo: {
|
|
||||||
dec: [0, 0, 0],
|
|
||||||
inc: [1, 0, 0],
|
|
||||||
total: [2, 1, 1],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.deepStrictEqual(chartDays, {
|
|
||||||
foo: {
|
|
||||||
dec: [0, 0, 0],
|
|
||||||
inc: [2, 0, 0],
|
|
||||||
total: [2, 0, 0],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Can specify offset", async () => {
|
|
||||||
await testChart.increment();
|
|
||||||
await testChart.save();
|
|
||||||
|
|
||||||
clock.tick("01:00:00");
|
|
||||||
|
|
||||||
await testChart.increment();
|
|
||||||
await testChart.save();
|
|
||||||
|
|
||||||
const chartHours = await testChart.getChart(
|
|
||||||
"hour",
|
|
||||||
3,
|
|
||||||
new Date(Date.UTC(2000, 0, 1, 0, 0, 0)),
|
|
||||||
);
|
|
||||||
const chartDays = await testChart.getChart(
|
|
||||||
"day",
|
|
||||||
3,
|
|
||||||
new Date(Date.UTC(2000, 0, 1, 0, 0, 0)),
|
|
||||||
);
|
|
||||||
|
|
||||||
assert.deepStrictEqual(chartHours, {
|
|
||||||
foo: {
|
|
||||||
dec: [0, 0, 0],
|
|
||||||
inc: [1, 0, 0],
|
|
||||||
total: [1, 0, 0],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.deepStrictEqual(chartDays, {
|
|
||||||
foo: {
|
|
||||||
dec: [0, 0, 0],
|
|
||||||
inc: [2, 0, 0],
|
|
||||||
total: [2, 0, 0],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Can specify offset (floor time)", async () => {
|
|
||||||
clock.tick("00:30:00");
|
|
||||||
|
|
||||||
await testChart.increment();
|
|
||||||
await testChart.save();
|
|
||||||
|
|
||||||
clock.tick("01:30:00");
|
|
||||||
|
|
||||||
await testChart.increment();
|
|
||||||
await testChart.save();
|
|
||||||
|
|
||||||
const chartHours = await testChart.getChart(
|
|
||||||
"hour",
|
|
||||||
3,
|
|
||||||
new Date(Date.UTC(2000, 0, 1, 0, 0, 0)),
|
|
||||||
);
|
|
||||||
const chartDays = await testChart.getChart(
|
|
||||||
"day",
|
|
||||||
3,
|
|
||||||
new Date(Date.UTC(2000, 0, 1, 0, 0, 0)),
|
|
||||||
);
|
|
||||||
|
|
||||||
assert.deepStrictEqual(chartHours, {
|
|
||||||
foo: {
|
|
||||||
dec: [0, 0, 0],
|
|
||||||
inc: [1, 0, 0],
|
|
||||||
total: [1, 0, 0],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.deepStrictEqual(chartDays, {
|
|
||||||
foo: {
|
|
||||||
dec: [0, 0, 0],
|
|
||||||
inc: [2, 0, 0],
|
|
||||||
total: [2, 0, 0],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("Grouped", () => {
|
|
||||||
it("Can updates", async () => {
|
|
||||||
await testGroupedChart.increment("alice");
|
|
||||||
await testGroupedChart.save();
|
|
||||||
|
|
||||||
const aliceChartHours = await testGroupedChart.getChart(
|
|
||||||
"hour",
|
|
||||||
3,
|
|
||||||
null,
|
|
||||||
"alice",
|
|
||||||
);
|
|
||||||
const aliceChartDays = await testGroupedChart.getChart(
|
|
||||||
"day",
|
|
||||||
3,
|
|
||||||
null,
|
|
||||||
"alice",
|
|
||||||
);
|
|
||||||
const bobChartHours = await testGroupedChart.getChart(
|
|
||||||
"hour",
|
|
||||||
3,
|
|
||||||
null,
|
|
||||||
"bob",
|
|
||||||
);
|
|
||||||
const bobChartDays = await testGroupedChart.getChart(
|
|
||||||
"day",
|
|
||||||
3,
|
|
||||||
null,
|
|
||||||
"bob",
|
|
||||||
);
|
|
||||||
|
|
||||||
assert.deepStrictEqual(aliceChartHours, {
|
|
||||||
foo: {
|
|
||||||
dec: [0, 0, 0],
|
|
||||||
inc: [1, 0, 0],
|
|
||||||
total: [1, 0, 0],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.deepStrictEqual(aliceChartDays, {
|
|
||||||
foo: {
|
|
||||||
dec: [0, 0, 0],
|
|
||||||
inc: [1, 0, 0],
|
|
||||||
total: [1, 0, 0],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.deepStrictEqual(bobChartHours, {
|
|
||||||
foo: {
|
|
||||||
dec: [0, 0, 0],
|
|
||||||
inc: [0, 0, 0],
|
|
||||||
total: [0, 0, 0],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.deepStrictEqual(bobChartDays, {
|
|
||||||
foo: {
|
|
||||||
dec: [0, 0, 0],
|
|
||||||
inc: [0, 0, 0],
|
|
||||||
total: [0, 0, 0],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("Unique increment", () => {
|
|
||||||
it("Can updates", async () => {
|
|
||||||
await testUniqueChart.uniqueIncrement("alice");
|
|
||||||
await testUniqueChart.uniqueIncrement("alice");
|
|
||||||
await testUniqueChart.uniqueIncrement("bob");
|
|
||||||
await testUniqueChart.save();
|
|
||||||
|
|
||||||
const chartHours = await testUniqueChart.getChart("hour", 3, null);
|
|
||||||
const chartDays = await testUniqueChart.getChart("day", 3, null);
|
|
||||||
|
|
||||||
assert.deepStrictEqual(chartHours, {
|
|
||||||
foo: [2, 0, 0],
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.deepStrictEqual(chartDays, {
|
|
||||||
foo: [2, 0, 0],
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("Intersection", () => {
|
|
||||||
it("条件が満たされていない場合はカウントされない", async () => {
|
|
||||||
await testIntersectionChart.addA("alice");
|
|
||||||
await testIntersectionChart.addA("bob");
|
|
||||||
await testIntersectionChart.addB("carol");
|
|
||||||
await testIntersectionChart.save();
|
|
||||||
|
|
||||||
const chartHours = await testIntersectionChart.getChart(
|
|
||||||
"hour",
|
|
||||||
3,
|
|
||||||
null,
|
|
||||||
);
|
|
||||||
const chartDays = await testIntersectionChart.getChart("day", 3, null);
|
|
||||||
|
|
||||||
assert.deepStrictEqual(chartHours, {
|
|
||||||
a: [2, 0, 0],
|
|
||||||
b: [1, 0, 0],
|
|
||||||
aAndB: [0, 0, 0],
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.deepStrictEqual(chartDays, {
|
|
||||||
a: [2, 0, 0],
|
|
||||||
b: [1, 0, 0],
|
|
||||||
aAndB: [0, 0, 0],
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("条件が満たされている場合にカウントされる", async () => {
|
|
||||||
await testIntersectionChart.addA("alice");
|
|
||||||
await testIntersectionChart.addA("bob");
|
|
||||||
await testIntersectionChart.addB("carol");
|
|
||||||
await testIntersectionChart.addB("alice");
|
|
||||||
await testIntersectionChart.save();
|
|
||||||
|
|
||||||
const chartHours = await testIntersectionChart.getChart(
|
|
||||||
"hour",
|
|
||||||
3,
|
|
||||||
null,
|
|
||||||
);
|
|
||||||
const chartDays = await testIntersectionChart.getChart("day", 3, null);
|
|
||||||
|
|
||||||
assert.deepStrictEqual(chartHours, {
|
|
||||||
a: [2, 0, 0],
|
|
||||||
b: [2, 0, 0],
|
|
||||||
aAndB: [1, 0, 0],
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.deepStrictEqual(chartDays, {
|
|
||||||
a: [2, 0, 0],
|
|
||||||
b: [2, 0, 0],
|
|
||||||
aAndB: [1, 0, 0],
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("Resync", () => {
|
|
||||||
it("Can resync", async () => {
|
|
||||||
testChart.total = 1;
|
|
||||||
|
|
||||||
await testChart.resync();
|
|
||||||
|
|
||||||
const chartHours = await testChart.getChart("hour", 3, null);
|
|
||||||
const chartDays = await testChart.getChart("day", 3, null);
|
|
||||||
|
|
||||||
assert.deepStrictEqual(chartHours, {
|
|
||||||
foo: {
|
|
||||||
dec: [0, 0, 0],
|
|
||||||
inc: [0, 0, 0],
|
|
||||||
total: [1, 0, 0],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.deepStrictEqual(chartDays, {
|
|
||||||
foo: {
|
|
||||||
dec: [0, 0, 0],
|
|
||||||
inc: [0, 0, 0],
|
|
||||||
total: [1, 0, 0],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Can resync (2)", async () => {
|
|
||||||
await testChart.increment();
|
|
||||||
await testChart.save();
|
|
||||||
|
|
||||||
clock.tick("01:00:00");
|
|
||||||
|
|
||||||
testChart.total = 100;
|
|
||||||
|
|
||||||
await testChart.resync();
|
|
||||||
|
|
||||||
const chartHours = await testChart.getChart("hour", 3, null);
|
|
||||||
const chartDays = await testChart.getChart("day", 3, null);
|
|
||||||
|
|
||||||
assert.deepStrictEqual(chartHours, {
|
|
||||||
foo: {
|
|
||||||
dec: [0, 0, 0],
|
|
||||||
inc: [0, 1, 0],
|
|
||||||
total: [100, 1, 0],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.deepStrictEqual(chartDays, {
|
|
||||||
foo: {
|
|
||||||
dec: [0, 0, 0],
|
|
||||||
inc: [1, 0, 0],
|
|
||||||
total: [100, 0, 0],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -15,7 +15,6 @@ import { defaultStore } from "@/store";
|
||||||
import { useChartTooltip } from "@/scripts/use-chart-tooltip";
|
import { useChartTooltip } from "@/scripts/use-chart-tooltip";
|
||||||
import { alpha } from "@/scripts/color";
|
import { alpha } from "@/scripts/color";
|
||||||
import { initChart } from "@/scripts/init-chart";
|
import { initChart } from "@/scripts/init-chart";
|
||||||
import { $i } from "@/reactiveAccount";
|
|
||||||
|
|
||||||
initChart();
|
initChart();
|
||||||
|
|
||||||
|
@ -26,20 +25,15 @@ const props = defineProps<{
|
||||||
const rootEl = shallowRef<HTMLDivElement>(null);
|
const rootEl = shallowRef<HTMLDivElement>(null);
|
||||||
const chartEl = shallowRef<HTMLCanvasElement>(null);
|
const chartEl = shallowRef<HTMLCanvasElement>(null);
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
let chartInstance: Chart = null,
|
let chartInstance: Chart | null = null;
|
||||||
fetching = ref(true);
|
const fetching = ref(true);
|
||||||
|
|
||||||
const { handler: externalTooltipHandler } = useChartTooltip({
|
const { handler: externalTooltipHandler } = useChartTooltip({
|
||||||
position: "middle",
|
position: "middle",
|
||||||
});
|
});
|
||||||
|
|
||||||
const addArrays = (arr1: number[], arr2: number[], arr3: number[]) =>
|
async function renderActiveUsersChart() {
|
||||||
arr1.length === arr2.length && arr2.length === arr3.length
|
if (chartInstance != null) {
|
||||||
? arr1.map((val, i) => val + arr2[i] + arr3[i])
|
|
||||||
: null;
|
|
||||||
|
|
||||||
async function renderChart() {
|
|
||||||
if (chartInstance) {
|
|
||||||
chartInstance.destroy();
|
chartInstance.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,46 +66,11 @@ async function renderChart() {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
let values;
|
const activeUsers = await os.api("charts/active-users", {
|
||||||
|
|
||||||
if (props.src === "active-users") {
|
|
||||||
const raw = await os.api("charts/active-users", {
|
|
||||||
limit: chartLimit,
|
limit: chartLimit,
|
||||||
span: "day",
|
span: "day",
|
||||||
});
|
});
|
||||||
values = raw.readWrite;
|
const values = activeUsers.readWrite;
|
||||||
} else if (props.src === "notes") {
|
|
||||||
const raw = await os.api("charts/notes", {
|
|
||||||
limit: chartLimit,
|
|
||||||
span: "day",
|
|
||||||
});
|
|
||||||
values = raw.local.inc;
|
|
||||||
} else if (props.src === "ap-requests-inbox-received") {
|
|
||||||
const raw = await os.api("charts/ap-request", {
|
|
||||||
limit: chartLimit,
|
|
||||||
span: "day",
|
|
||||||
});
|
|
||||||
values = raw.inboxReceived;
|
|
||||||
} else if (props.src === "ap-requests-deliver-succeeded") {
|
|
||||||
const raw = await os.api("charts/ap-request", {
|
|
||||||
limit: chartLimit,
|
|
||||||
span: "day",
|
|
||||||
});
|
|
||||||
values = raw.deliverSucceeded;
|
|
||||||
} else if (props.src === "ap-requests-deliver-failed") {
|
|
||||||
const raw = await os.api("charts/ap-request", {
|
|
||||||
limit: chartLimit,
|
|
||||||
span: "day",
|
|
||||||
});
|
|
||||||
values = raw.deliverFailed;
|
|
||||||
} else if (props.src === "my-notes") {
|
|
||||||
const raw = await os.api("charts/user/notes", {
|
|
||||||
limit: chartLimit,
|
|
||||||
span: "day",
|
|
||||||
userId: $i.id,
|
|
||||||
});
|
|
||||||
values = addArrays(raw.diffs.normal, raw.diffs.reply, raw.diffs.renote);
|
|
||||||
}
|
|
||||||
|
|
||||||
fetching.value = false;
|
fetching.value = false;
|
||||||
|
|
||||||
|
@ -248,11 +207,11 @@ watch(
|
||||||
() => props.src,
|
() => props.src,
|
||||||
() => {
|
() => {
|
||||||
fetching.value = true;
|
fetching.value = true;
|
||||||
renderChart();
|
renderActiveUsersChart();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
renderChart();
|
renderActiveUsersChart();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
|
@ -361,239 +361,6 @@ const render = () => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const exportData = () => {
|
|
||||||
// TODO
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchFederationChart = async (): Promise<typeof chartData> => {
|
|
||||||
const raw = await os.apiGet("charts/federation", {
|
|
||||||
limit: props.limit,
|
|
||||||
span: props.span,
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: "Received",
|
|
||||||
type: "area",
|
|
||||||
data: format(raw.inboxInstances),
|
|
||||||
color: colors.blue,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Delivered",
|
|
||||||
type: "area",
|
|
||||||
data: format(raw.deliveredInstances),
|
|
||||||
color: colors.green,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Stalled",
|
|
||||||
type: "area",
|
|
||||||
data: format(raw.stalled),
|
|
||||||
color: colors.red,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Pub Active",
|
|
||||||
type: "line",
|
|
||||||
data: format(raw.pubActive),
|
|
||||||
color: colors.purple,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Sub Active",
|
|
||||||
type: "line",
|
|
||||||
data: format(raw.subActive),
|
|
||||||
color: colors.orange,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Pub & Sub",
|
|
||||||
type: "line",
|
|
||||||
data: format(raw.pubsub),
|
|
||||||
dashed: true,
|
|
||||||
color: colors.cyan,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Pub",
|
|
||||||
type: "line",
|
|
||||||
data: format(raw.pub),
|
|
||||||
dashed: true,
|
|
||||||
color: colors.purple,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Sub",
|
|
||||||
type: "line",
|
|
||||||
data: format(raw.sub),
|
|
||||||
dashed: true,
|
|
||||||
color: colors.orange,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchApRequestChart = async (): Promise<typeof chartData> => {
|
|
||||||
const raw = await os.apiGet("charts/ap-request", {
|
|
||||||
limit: props.limit,
|
|
||||||
span: props.span,
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: "In",
|
|
||||||
type: "area",
|
|
||||||
color: "#31748f",
|
|
||||||
data: format(raw.inboxReceived),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Out (succ)",
|
|
||||||
type: "area",
|
|
||||||
color: "#c4a7e7",
|
|
||||||
data: format(raw.deliverSucceeded),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Out (fail)",
|
|
||||||
type: "area",
|
|
||||||
color: "#f6c177",
|
|
||||||
data: format(raw.deliverFailed),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchNotesChart = async (type: string): Promise<typeof chartData> => {
|
|
||||||
const raw = await os.apiGet("charts/notes", {
|
|
||||||
limit: props.limit,
|
|
||||||
span: props.span,
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: "All",
|
|
||||||
type: "line",
|
|
||||||
data: format(
|
|
||||||
type === "combined"
|
|
||||||
? sum(
|
|
||||||
raw.local.inc,
|
|
||||||
negate(raw.local.dec),
|
|
||||||
raw.remote.inc,
|
|
||||||
negate(raw.remote.dec),
|
|
||||||
)
|
|
||||||
: sum(raw[type].inc, negate(raw[type].dec)),
|
|
||||||
),
|
|
||||||
color: "#888888",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Renotes",
|
|
||||||
type: "area",
|
|
||||||
data: format(
|
|
||||||
type === "combined"
|
|
||||||
? sum(raw.local.diffs.renote, raw.remote.diffs.renote)
|
|
||||||
: raw[type].diffs.renote,
|
|
||||||
),
|
|
||||||
color: colors.green,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Replies",
|
|
||||||
type: "area",
|
|
||||||
data: format(
|
|
||||||
type === "combined"
|
|
||||||
? sum(raw.local.diffs.reply, raw.remote.diffs.reply)
|
|
||||||
: raw[type].diffs.reply,
|
|
||||||
),
|
|
||||||
color: colors.yellow,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Normal",
|
|
||||||
type: "area",
|
|
||||||
data: format(
|
|
||||||
type === "combined"
|
|
||||||
? sum(raw.local.diffs.normal, raw.remote.diffs.normal)
|
|
||||||
: raw[type].diffs.normal,
|
|
||||||
),
|
|
||||||
color: colors.blue,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "With file",
|
|
||||||
type: "area",
|
|
||||||
data: format(
|
|
||||||
type === "combined"
|
|
||||||
? sum(
|
|
||||||
raw.local.diffs.withFile,
|
|
||||||
raw.remote.diffs.withFile,
|
|
||||||
)
|
|
||||||
: raw[type].diffs.withFile,
|
|
||||||
),
|
|
||||||
color: colors.purple,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchNotesTotalChart = async (): Promise<typeof chartData> => {
|
|
||||||
const raw = await os.apiGet("charts/notes", {
|
|
||||||
limit: props.limit,
|
|
||||||
span: props.span,
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: "Combined",
|
|
||||||
type: "line",
|
|
||||||
data: format(sum(raw.local.total, raw.remote.total)),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Local",
|
|
||||||
type: "area",
|
|
||||||
data: format(raw.local.total),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Remote",
|
|
||||||
type: "area",
|
|
||||||
data: format(raw.remote.total),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchUsersChart = async (total: boolean): Promise<typeof chartData> => {
|
|
||||||
const raw = await os.apiGet("charts/users", {
|
|
||||||
limit: props.limit,
|
|
||||||
span: props.span,
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: "Combined",
|
|
||||||
type: "line",
|
|
||||||
data: format(
|
|
||||||
total
|
|
||||||
? sum(raw.local.total, raw.remote.total)
|
|
||||||
: sum(
|
|
||||||
raw.local.inc,
|
|
||||||
negate(raw.local.dec),
|
|
||||||
raw.remote.inc,
|
|
||||||
negate(raw.remote.dec),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Local",
|
|
||||||
type: "area",
|
|
||||||
data: format(
|
|
||||||
total
|
|
||||||
? raw.local.total
|
|
||||||
: sum(raw.local.inc, negate(raw.local.dec)),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Remote",
|
|
||||||
type: "area",
|
|
||||||
data: format(
|
|
||||||
total
|
|
||||||
? raw.remote.total
|
|
||||||
: sum(raw.remote.inc, negate(raw.remote.dec)),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchActiveUsersChart = async (): Promise<typeof chartData> => {
|
const fetchActiveUsersChart = async (): Promise<typeof chartData> => {
|
||||||
const raw = await os.apiGet("charts/active-users", {
|
const raw = await os.apiGet("charts/active-users", {
|
||||||
limit: props.limit,
|
limit: props.limit,
|
||||||
|
@ -659,428 +426,9 @@ const fetchActiveUsersChart = async (): Promise<typeof chartData> => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchDriveChart = async (): Promise<typeof chartData> => {
|
|
||||||
const raw = await os.apiGet("charts/drive", {
|
|
||||||
limit: props.limit,
|
|
||||||
span: props.span,
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
bytes: true,
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: "All",
|
|
||||||
type: "line",
|
|
||||||
dashed: true,
|
|
||||||
data: format(
|
|
||||||
sum(
|
|
||||||
raw.local.incSize,
|
|
||||||
negate(raw.local.decSize),
|
|
||||||
raw.remote.incSize,
|
|
||||||
negate(raw.remote.decSize),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Local +",
|
|
||||||
type: "area",
|
|
||||||
data: format(raw.local.incSize),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Local -",
|
|
||||||
type: "area",
|
|
||||||
data: format(negate(raw.local.decSize)),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Remote +",
|
|
||||||
type: "area",
|
|
||||||
data: format(raw.remote.incSize),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Remote -",
|
|
||||||
type: "area",
|
|
||||||
data: format(negate(raw.remote.decSize)),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchDriveFilesChart = async (): Promise<typeof chartData> => {
|
|
||||||
const raw = await os.apiGet("charts/drive", {
|
|
||||||
limit: props.limit,
|
|
||||||
span: props.span,
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: "All",
|
|
||||||
type: "line",
|
|
||||||
dashed: true,
|
|
||||||
data: format(
|
|
||||||
sum(
|
|
||||||
raw.local.incCount,
|
|
||||||
negate(raw.local.decCount),
|
|
||||||
raw.remote.incCount,
|
|
||||||
negate(raw.remote.decCount),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Local +",
|
|
||||||
type: "area",
|
|
||||||
data: format(raw.local.incCount),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Local -",
|
|
||||||
type: "area",
|
|
||||||
data: format(negate(raw.local.decCount)),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Remote +",
|
|
||||||
type: "area",
|
|
||||||
data: format(raw.remote.incCount),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Remote -",
|
|
||||||
type: "area",
|
|
||||||
data: format(negate(raw.remote.decCount)),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchInstanceRequestsChart = async (): Promise<typeof chartData> => {
|
|
||||||
const raw = await os.apiGet("charts/instance", {
|
|
||||||
host: props.args.host,
|
|
||||||
limit: props.limit,
|
|
||||||
span: props.span,
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: "In",
|
|
||||||
type: "area",
|
|
||||||
color: "#31748f",
|
|
||||||
data: format(raw.requests.received),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Out (succ)",
|
|
||||||
type: "area",
|
|
||||||
color: "#c4a7e7",
|
|
||||||
data: format(raw.requests.succeeded),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Out (fail)",
|
|
||||||
type: "area",
|
|
||||||
color: "#f6c177",
|
|
||||||
data: format(raw.requests.failed),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchInstanceUsersChart = async (
|
|
||||||
total: boolean,
|
|
||||||
): Promise<typeof chartData> => {
|
|
||||||
const raw = await os.apiGet("charts/instance", {
|
|
||||||
host: props.args.host,
|
|
||||||
limit: props.limit,
|
|
||||||
span: props.span,
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: "Users",
|
|
||||||
type: "area",
|
|
||||||
color: "#31748f",
|
|
||||||
data: format(
|
|
||||||
total
|
|
||||||
? raw.users.total
|
|
||||||
: sum(raw.users.inc, negate(raw.users.dec)),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchInstanceNotesChart = async (
|
|
||||||
total: boolean,
|
|
||||||
): Promise<typeof chartData> => {
|
|
||||||
const raw = await os.apiGet("charts/instance", {
|
|
||||||
host: props.args.host,
|
|
||||||
limit: props.limit,
|
|
||||||
span: props.span,
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: "Posts",
|
|
||||||
type: "area",
|
|
||||||
color: "#31748f",
|
|
||||||
data: format(
|
|
||||||
total
|
|
||||||
? raw.notes.total
|
|
||||||
: sum(raw.notes.inc, negate(raw.notes.dec)),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchInstanceFfChart = async (
|
|
||||||
total: boolean,
|
|
||||||
): Promise<typeof chartData> => {
|
|
||||||
const raw = await os.apiGet("charts/instance", {
|
|
||||||
host: props.args.host,
|
|
||||||
limit: props.limit,
|
|
||||||
span: props.span,
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: "Following",
|
|
||||||
type: "area",
|
|
||||||
color: "#31748f",
|
|
||||||
data: format(
|
|
||||||
total
|
|
||||||
? raw.following.total
|
|
||||||
: sum(raw.following.inc, negate(raw.following.dec)),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Followers",
|
|
||||||
type: "area",
|
|
||||||
color: "#c4a7e7",
|
|
||||||
data: format(
|
|
||||||
total
|
|
||||||
? raw.followers.total
|
|
||||||
: sum(raw.followers.inc, negate(raw.followers.dec)),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchInstanceDriveUsageChart = async (
|
|
||||||
total: boolean,
|
|
||||||
): Promise<typeof chartData> => {
|
|
||||||
const raw = await os.apiGet("charts/instance", {
|
|
||||||
host: props.args.host,
|
|
||||||
limit: props.limit,
|
|
||||||
span: props.span,
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
bytes: true,
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: "Drive usage",
|
|
||||||
type: "area",
|
|
||||||
color: "#31748f",
|
|
||||||
data: format(
|
|
||||||
total
|
|
||||||
? raw.drive.totalUsage
|
|
||||||
: sum(raw.drive.incUsage, negate(raw.drive.decUsage)),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchInstanceDriveFilesChart = async (
|
|
||||||
total: boolean,
|
|
||||||
): Promise<typeof chartData> => {
|
|
||||||
const raw = await os.apiGet("charts/instance", {
|
|
||||||
host: props.args.host,
|
|
||||||
limit: props.limit,
|
|
||||||
span: props.span,
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: "Drive files",
|
|
||||||
type: "area",
|
|
||||||
color: "#31748f",
|
|
||||||
data: format(
|
|
||||||
total
|
|
||||||
? raw.drive.totalFiles
|
|
||||||
: sum(raw.drive.incFiles, negate(raw.drive.decFiles)),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchPerUserNotesChart = async (): Promise<typeof chartData> => {
|
|
||||||
const raw = await os.apiGet("charts/user/notes", {
|
|
||||||
userId: props.args.user.id,
|
|
||||||
limit: props.limit,
|
|
||||||
span: props.span,
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
series: [
|
|
||||||
...(props.args.withoutAll
|
|
||||||
? []
|
|
||||||
: [
|
|
||||||
{
|
|
||||||
name: "All",
|
|
||||||
type: "line",
|
|
||||||
data: format(sum(raw.inc, negate(raw.dec))),
|
|
||||||
color: "#888888",
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
{
|
|
||||||
name: "With file",
|
|
||||||
type: "area",
|
|
||||||
data: format(raw.diffs.withFile),
|
|
||||||
color: colors.purple,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Renotes",
|
|
||||||
type: "area",
|
|
||||||
data: format(raw.diffs.renote),
|
|
||||||
color: colors.green,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Replies",
|
|
||||||
type: "area",
|
|
||||||
data: format(raw.diffs.reply),
|
|
||||||
color: colors.yellow,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Normal",
|
|
||||||
type: "area",
|
|
||||||
data: format(raw.diffs.normal),
|
|
||||||
color: colors.blue,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchPerUserFollowingChart = async (): Promise<typeof chartData> => {
|
|
||||||
const raw = await os.apiGet("charts/user/following", {
|
|
||||||
userId: props.args.user.id,
|
|
||||||
limit: props.limit,
|
|
||||||
span: props.span,
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: "Local",
|
|
||||||
type: "area",
|
|
||||||
data: format(raw.local.followings.total),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Remote",
|
|
||||||
type: "area",
|
|
||||||
data: format(raw.remote.followings.total),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchPerUserFollowersChart = async (): Promise<typeof chartData> => {
|
|
||||||
const raw = await os.apiGet("charts/user/following", {
|
|
||||||
userId: props.args.user.id,
|
|
||||||
limit: props.limit,
|
|
||||||
span: props.span,
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: "Local",
|
|
||||||
type: "area",
|
|
||||||
data: format(raw.local.followers.total),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Remote",
|
|
||||||
type: "area",
|
|
||||||
data: format(raw.remote.followers.total),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchPerUserDriveChart = async (): Promise<typeof chartData> => {
|
|
||||||
const raw = await os.apiGet("charts/user/drive", {
|
|
||||||
userId: props.args.user.id,
|
|
||||||
limit: props.limit,
|
|
||||||
span: props.span,
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: "Inc",
|
|
||||||
type: "area",
|
|
||||||
data: format(raw.incSize),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Dec",
|
|
||||||
type: "area",
|
|
||||||
data: format(raw.decSize),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchAndRender = async () => {
|
const fetchAndRender = async () => {
|
||||||
const fetchData = () => {
|
|
||||||
switch (props.src) {
|
|
||||||
case "federation":
|
|
||||||
return fetchFederationChart();
|
|
||||||
case "ap-request":
|
|
||||||
return fetchApRequestChart();
|
|
||||||
case "users":
|
|
||||||
return fetchUsersChart(false);
|
|
||||||
case "users-total":
|
|
||||||
return fetchUsersChart(true);
|
|
||||||
case "active-users":
|
|
||||||
return fetchActiveUsersChart();
|
|
||||||
case "notes":
|
|
||||||
return fetchNotesChart("combined");
|
|
||||||
case "local-notes":
|
|
||||||
return fetchNotesChart("local");
|
|
||||||
case "remote-notes":
|
|
||||||
return fetchNotesChart("remote");
|
|
||||||
case "notes-total":
|
|
||||||
return fetchNotesTotalChart();
|
|
||||||
case "drive":
|
|
||||||
return fetchDriveChart();
|
|
||||||
case "drive-files":
|
|
||||||
return fetchDriveFilesChart();
|
|
||||||
case "instance-requests":
|
|
||||||
return fetchInstanceRequestsChart();
|
|
||||||
case "instance-users":
|
|
||||||
return fetchInstanceUsersChart(false);
|
|
||||||
case "instance-users-total":
|
|
||||||
return fetchInstanceUsersChart(true);
|
|
||||||
case "instance-notes":
|
|
||||||
return fetchInstanceNotesChart(false);
|
|
||||||
case "instance-notes-total":
|
|
||||||
return fetchInstanceNotesChart(true);
|
|
||||||
case "instance-ff":
|
|
||||||
return fetchInstanceFfChart(false);
|
|
||||||
case "instance-ff-total":
|
|
||||||
return fetchInstanceFfChart(true);
|
|
||||||
case "instance-drive-usage":
|
|
||||||
return fetchInstanceDriveUsageChart(false);
|
|
||||||
case "instance-drive-usage-total":
|
|
||||||
return fetchInstanceDriveUsageChart(true);
|
|
||||||
case "instance-drive-files":
|
|
||||||
return fetchInstanceDriveFilesChart(false);
|
|
||||||
case "instance-drive-files-total":
|
|
||||||
return fetchInstanceDriveFilesChart(true);
|
|
||||||
|
|
||||||
case "per-user-notes":
|
|
||||||
return fetchPerUserNotesChart();
|
|
||||||
case "per-user-following":
|
|
||||||
return fetchPerUserFollowingChart();
|
|
||||||
case "per-user-followers":
|
|
||||||
return fetchPerUserFollowersChart();
|
|
||||||
case "per-user-drive":
|
|
||||||
return fetchPerUserDriveChart();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
fetching.value = true;
|
fetching.value = true;
|
||||||
chartData = await fetchData();
|
chartData = await fetchActiveUsersChart();
|
||||||
fetching.value = false;
|
fetching.value = false;
|
||||||
render();
|
render();
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
{{ instance.softwareVersion }}</span
|
{{ instance.softwareVersion }}</span
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<MkMiniChart v-if="chartValues" class="chart" :src="chartValues" />
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -27,7 +26,6 @@
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
|
|
||||||
import type { entities } from "firefish-js";
|
import type { entities } from "firefish-js";
|
||||||
import MkMiniChart from "@/components/MkMiniChart.vue";
|
|
||||||
import * as os from "@/os";
|
import * as os from "@/os";
|
||||||
import { getProxiedImageUrlNullable } from "@/scripts/media-proxy";
|
import { getProxiedImageUrlNullable } from "@/scripts/media-proxy";
|
||||||
|
|
||||||
|
@ -35,18 +33,6 @@ const props = defineProps<{
|
||||||
instance: entities.Instance;
|
instance: entities.Instance;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const chartValues = ref<number[] | null>(null);
|
|
||||||
|
|
||||||
os.apiGet("charts/instance", {
|
|
||||||
host: props.instance.host,
|
|
||||||
limit: 16 + 1,
|
|
||||||
span: "day",
|
|
||||||
}).then((res) => {
|
|
||||||
// 今日のぶんの値はまだ途中の値であり、それも含めると大抵の場合前日よりも下降しているようなグラフになってしまうため今日は弾く
|
|
||||||
res.requests.received.splice(0, 1);
|
|
||||||
chartValues.value = res.requests.received;
|
|
||||||
});
|
|
||||||
|
|
||||||
function getInstanceIcon(instance): string {
|
function getInstanceIcon(instance): string {
|
||||||
return (
|
return (
|
||||||
getProxiedImageUrlNullable(instance.faviconUrl, "preview") ??
|
getProxiedImageUrlNullable(instance.faviconUrl, "preview") ??
|
||||||
|
@ -104,10 +90,6 @@ function getInstanceIcon(instance): string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> :global(.chart) {
|
|
||||||
height: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:global(.yellow) {
|
&:global(.yellow) {
|
||||||
--c: rgb(255 196 0 / 15%);
|
--c: rgb(255 196 0 / 15%);
|
||||||
background-image: linear-gradient(
|
background-image: linear-gradient(
|
||||||
|
|
|
@ -1,52 +1,9 @@
|
||||||
<template>
|
<template>
|
||||||
<div :class="$style.root">
|
<div :class="$style.root">
|
||||||
<MkFolder class="item">
|
<MkFolder class="item">
|
||||||
<template #header>Chart</template>
|
<template #header>Active Users</template>
|
||||||
<div :class="$style.chart">
|
<div :class="$style.chart">
|
||||||
<div class="selects">
|
<div class="selects">
|
||||||
<MkSelect v-model="chartSrc" style="margin: 0; flex: 1">
|
|
||||||
<optgroup :label="i18n.ts.federation">
|
|
||||||
<option value="federation">
|
|
||||||
{{ i18n.ts._charts.federation }}
|
|
||||||
</option>
|
|
||||||
<option value="ap-request">
|
|
||||||
{{ i18n.ts._charts.apRequest }}
|
|
||||||
</option>
|
|
||||||
</optgroup>
|
|
||||||
<optgroup :label="i18n.ts.users">
|
|
||||||
<option value="users">
|
|
||||||
{{ i18n.ts._charts.usersIncDec }}
|
|
||||||
</option>
|
|
||||||
<option value="users-total">
|
|
||||||
{{ i18n.ts._charts.usersTotal }}
|
|
||||||
</option>
|
|
||||||
<option value="active-users">
|
|
||||||
{{ i18n.ts._charts.activeUsers }}
|
|
||||||
</option>
|
|
||||||
</optgroup>
|
|
||||||
<optgroup :label="i18n.ts.notes">
|
|
||||||
<option value="notes">
|
|
||||||
{{ i18n.ts._charts.notesIncDec }}
|
|
||||||
</option>
|
|
||||||
<option value="local-notes">
|
|
||||||
{{ i18n.ts._charts.localNotesIncDec }}
|
|
||||||
</option>
|
|
||||||
<option value="remote-notes">
|
|
||||||
{{ i18n.ts._charts.remoteNotesIncDec }}
|
|
||||||
</option>
|
|
||||||
<option value="notes-total">
|
|
||||||
{{ i18n.ts._charts.notesTotal }}
|
|
||||||
</option>
|
|
||||||
</optgroup>
|
|
||||||
<optgroup :label="i18n.ts.drive">
|
|
||||||
<option value="drive-files">
|
|
||||||
{{ i18n.ts._charts.filesIncDec }}
|
|
||||||
</option>
|
|
||||||
<option value="drive">
|
|
||||||
{{ i18n.ts._charts.storageUsageIncDec }}
|
|
||||||
</option>
|
|
||||||
</optgroup>
|
|
||||||
</MkSelect>
|
|
||||||
<MkSelect v-model="chartSpan" style="margin: 0 0 0 10px">
|
<MkSelect v-model="chartSpan" style="margin: 0 0 0 10px">
|
||||||
<option value="hour">{{ i18n.ts.perHour }}</option>
|
<option value="hour">{{ i18n.ts.perHour }}</option>
|
||||||
<option value="day">{{ i18n.ts.perDay }}</option>
|
<option value="day">{{ i18n.ts.perDay }}</option>
|
||||||
|
@ -54,32 +11,15 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="chart _panel">
|
<div class="chart _panel">
|
||||||
<MkChart
|
<MkChart
|
||||||
:src="chartSrc"
|
src="active-users"
|
||||||
:span="chartSpan"
|
:span="chartSpan"
|
||||||
:limit="chartLimit"
|
:limit="chartLimit"
|
||||||
:detailed="true"
|
:detailed="true"
|
||||||
></MkChart>
|
></MkChart>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</MkFolder>
|
|
||||||
|
|
||||||
<MkFolder class="item">
|
|
||||||
<template #header>Active users heatmap</template>
|
|
||||||
<MkSelect v-model="heatmapSrc" style="margin: 0 0 12px 0">
|
|
||||||
<option value="active-users">Active users</option>
|
|
||||||
<option value="notes">Posts</option>
|
|
||||||
<option value="ap-requests-inbox-received">
|
|
||||||
Fediverse Requests: inboxReceived
|
|
||||||
</option>
|
|
||||||
<option value="ap-requests-deliver-succeeded">
|
|
||||||
Fediverse Requests: deliverSucceeded
|
|
||||||
</option>
|
|
||||||
<option value="ap-requests-deliver-failed">
|
|
||||||
Fediverse Requests: deliverFailed
|
|
||||||
</option>
|
|
||||||
</MkSelect>
|
|
||||||
<div class="_panel" :class="$style.heatmap">
|
<div class="_panel" :class="$style.heatmap">
|
||||||
<MkHeatmap :src="heatmapSrc" />
|
<MkActiveUsersHeatmap />
|
||||||
</div>
|
</div>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
|
@ -109,7 +49,7 @@ import MkChart from "@/components/MkChart.vue";
|
||||||
import { useChartTooltip } from "@/scripts/use-chart-tooltip";
|
import { useChartTooltip } from "@/scripts/use-chart-tooltip";
|
||||||
import * as os from "@/os";
|
import * as os from "@/os";
|
||||||
import { i18n } from "@/i18n";
|
import { i18n } from "@/i18n";
|
||||||
import MkHeatmap from "@/components/MkHeatmap.vue";
|
import MkActiveUsersHeatmap from "@/components/MkActiveUsersHeatmap.vue";
|
||||||
import MkFolder from "@/components/MkFolder.vue";
|
import MkFolder from "@/components/MkFolder.vue";
|
||||||
import { initChart } from "@/scripts/init-chart";
|
import { initChart } from "@/scripts/init-chart";
|
||||||
|
|
||||||
|
@ -117,8 +57,6 @@ initChart();
|
||||||
|
|
||||||
const chartLimit = 500;
|
const chartLimit = 500;
|
||||||
const chartSpan = ref<"hour" | "day">("hour");
|
const chartSpan = ref<"hour" | "day">("hour");
|
||||||
const chartSrc = ref("active-users");
|
|
||||||
const heatmapSrc = ref("active-users");
|
|
||||||
const subDoughnutEl = shallowRef<HTMLCanvasElement>();
|
const subDoughnutEl = shallowRef<HTMLCanvasElement>();
|
||||||
const pubDoughnutEl = shallowRef<HTMLCanvasElement>();
|
const pubDoughnutEl = shallowRef<HTMLCanvasElement>();
|
||||||
|
|
||||||
|
|
|
@ -115,7 +115,6 @@
|
||||||
v-if="tab === 'renotes' && renotes"
|
v-if="tab === 'renotes' && renotes"
|
||||||
:key="item.user.id"
|
:key="item.user.id"
|
||||||
:user="item.user"
|
:user="item.user"
|
||||||
:with-chart="false"
|
|
||||||
/>
|
/>
|
||||||
<!-- </MkPagination> -->
|
<!-- </MkPagination> -->
|
||||||
<MkLoading v-else-if="tab === 'renotes' && note.renoteCount > 0" />
|
<MkLoading v-else-if="tab === 'renotes' && note.renoteCount > 0" />
|
||||||
|
|
|
@ -23,12 +23,7 @@
|
||||||
}}</span>
|
}}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<MkUserCardMini
|
<MkUserCardMini v-for="user in users" :key="user.id" :user="user" />
|
||||||
v-for="user in users"
|
|
||||||
:key="user.id"
|
|
||||||
:user="user"
|
|
||||||
:with-chart="false"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<MkLoading />
|
<MkLoading />
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
></span
|
></span
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<MkMiniChart v-if="chartValues" class="chart" :src="chartValues" />
|
|
||||||
</MkA>
|
</MkA>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -29,35 +28,17 @@
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
|
|
||||||
import { acct, type entities } from "firefish-js";
|
import { acct, type entities } from "firefish-js";
|
||||||
import MkMiniChart from "@/components/MkMiniChart.vue";
|
|
||||||
import * as os from "@/os";
|
|
||||||
import { userPage } from "@/filters/user";
|
import { userPage } from "@/filters/user";
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
user: entities.User;
|
user: entities.User;
|
||||||
withChart?: boolean;
|
|
||||||
showAboutPage?: boolean;
|
showAboutPage?: boolean;
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
withChart: true,
|
|
||||||
showAboutPage: false,
|
showAboutPage: false,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const chartValues = ref<number[] | null>(null);
|
|
||||||
|
|
||||||
if (props.withChart) {
|
|
||||||
os.apiGet("charts/user/notes", {
|
|
||||||
userId: props.user.id,
|
|
||||||
limit: 16 + 1,
|
|
||||||
span: "day",
|
|
||||||
}).then((res) => {
|
|
||||||
// 今日のぶんの値はまだ途中の値であり、それも含めると大抵の場合前日よりも下降しているようなグラフになってしまうため今日は弾く
|
|
||||||
res.inc.splice(0, 1);
|
|
||||||
chartValues.value = res.inc;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
|
|
|
@ -1,289 +0,0 @@
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<MkLoading v-if="fetching" />
|
|
||||||
<div v-show="!fetching" :class="$style.root">
|
|
||||||
<div class="charts _panel">
|
|
||||||
<div class="chart">
|
|
||||||
<canvas ref="chartEl2"></canvas>
|
|
||||||
</div>
|
|
||||||
<div class="chart">
|
|
||||||
<canvas ref="chartEl"></canvas>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { onMounted, ref, shallowRef } from "vue";
|
|
||||||
import { Chart } from "chart.js";
|
|
||||||
import gradient from "chartjs-plugin-gradient";
|
|
||||||
import * as os from "@/os";
|
|
||||||
import { useChartTooltip } from "@/scripts/use-chart-tooltip";
|
|
||||||
import { chartVLine } from "@/scripts/chart-vline";
|
|
||||||
import { defaultStore } from "@/store";
|
|
||||||
import { alpha } from "@/scripts/color";
|
|
||||||
import { initChart } from "@/scripts/init-chart";
|
|
||||||
|
|
||||||
initChart();
|
|
||||||
|
|
||||||
const chartLimit = 50;
|
|
||||||
const chartEl = shallowRef<HTMLCanvasElement>();
|
|
||||||
const chartEl2 = shallowRef<HTMLCanvasElement>();
|
|
||||||
const fetching = ref(true);
|
|
||||||
|
|
||||||
const { handler: externalTooltipHandler } = useChartTooltip();
|
|
||||||
const { handler: externalTooltipHandler2 } = useChartTooltip();
|
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
const now = new Date();
|
|
||||||
|
|
||||||
const getDate = (ago: number) => {
|
|
||||||
const y = now.getFullYear();
|
|
||||||
const m = now.getMonth();
|
|
||||||
const d = now.getDate();
|
|
||||||
|
|
||||||
return new Date(y, m, d - ago);
|
|
||||||
};
|
|
||||||
|
|
||||||
const format = (arr) => {
|
|
||||||
return arr.map((v, i) => ({
|
|
||||||
x: getDate(i).getTime(),
|
|
||||||
y: v,
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
const formatMinus = (arr) => {
|
|
||||||
return arr.map((v, i) => ({
|
|
||||||
x: getDate(i).getTime(),
|
|
||||||
y: -v,
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
const raw = await os.api("charts/ap-request", {
|
|
||||||
limit: chartLimit,
|
|
||||||
span: "day",
|
|
||||||
});
|
|
||||||
|
|
||||||
const vLineColor = defaultStore.state.darkMode
|
|
||||||
? "rgba(255, 255, 255, 0.2)"
|
|
||||||
: "rgba(0, 0, 0, 0.2)";
|
|
||||||
const succColor = "#9ccfd8";
|
|
||||||
const failColor = "#f6c177";
|
|
||||||
|
|
||||||
new Chart(chartEl.value, {
|
|
||||||
type: "line",
|
|
||||||
data: {
|
|
||||||
datasets: [
|
|
||||||
{
|
|
||||||
stack: "a",
|
|
||||||
parsing: false,
|
|
||||||
label: "Out: Succ",
|
|
||||||
data: format(raw.deliverSucceeded).slice().reverse(),
|
|
||||||
tension: 0.3,
|
|
||||||
pointRadius: 0,
|
|
||||||
borderWidth: 2,
|
|
||||||
borderColor: succColor,
|
|
||||||
borderJoinStyle: "round",
|
|
||||||
borderRadius: 4,
|
|
||||||
backgroundColor: alpha(succColor, 0.35),
|
|
||||||
fill: true,
|
|
||||||
clip: 8,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
stack: "a",
|
|
||||||
parsing: false,
|
|
||||||
label: "Out: Fail",
|
|
||||||
data: formatMinus(raw.deliverFailed).slice().reverse(),
|
|
||||||
tension: 0.3,
|
|
||||||
pointRadius: 0,
|
|
||||||
borderWidth: 2,
|
|
||||||
borderColor: failColor,
|
|
||||||
borderJoinStyle: "round",
|
|
||||||
borderRadius: 4,
|
|
||||||
backgroundColor: alpha(failColor, 0.35),
|
|
||||||
fill: true,
|
|
||||||
clip: 8,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
aspectRatio: 2.5,
|
|
||||||
layout: {
|
|
||||||
padding: {
|
|
||||||
left: 0,
|
|
||||||
right: 8,
|
|
||||||
top: 0,
|
|
||||||
bottom: 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
scales: {
|
|
||||||
x: {
|
|
||||||
type: "time",
|
|
||||||
stacked: true,
|
|
||||||
offset: false,
|
|
||||||
time: {
|
|
||||||
stepSize: 1,
|
|
||||||
unit: "day",
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
display: true,
|
|
||||||
},
|
|
||||||
ticks: {
|
|
||||||
display: true,
|
|
||||||
maxRotation: 0,
|
|
||||||
autoSkipPadding: 16,
|
|
||||||
},
|
|
||||||
min: getDate(chartLimit).getTime(),
|
|
||||||
},
|
|
||||||
y: {
|
|
||||||
stacked: true,
|
|
||||||
position: "left",
|
|
||||||
suggestedMax: 10,
|
|
||||||
grid: {
|
|
||||||
display: true,
|
|
||||||
},
|
|
||||||
ticks: {
|
|
||||||
display: true,
|
|
||||||
// mirror: true,
|
|
||||||
callback: (value, index, values) =>
|
|
||||||
value < 0 ? -value : value,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
interaction: {
|
|
||||||
intersect: false,
|
|
||||||
mode: "index",
|
|
||||||
},
|
|
||||||
elements: {
|
|
||||||
point: {
|
|
||||||
hoverRadius: 5,
|
|
||||||
hoverBorderWidth: 2,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: {
|
|
||||||
legend: {
|
|
||||||
display: false,
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
enabled: false,
|
|
||||||
mode: "index",
|
|
||||||
animation: {
|
|
||||||
duration: 0,
|
|
||||||
},
|
|
||||||
external: externalTooltipHandler,
|
|
||||||
},
|
|
||||||
gradient,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: [chartVLine(vLineColor)],
|
|
||||||
});
|
|
||||||
|
|
||||||
new Chart(chartEl2.value, {
|
|
||||||
type: "bar",
|
|
||||||
data: {
|
|
||||||
datasets: [
|
|
||||||
{
|
|
||||||
parsing: false,
|
|
||||||
label: "In",
|
|
||||||
data: format(raw.inboxReceived).slice().reverse(),
|
|
||||||
tension: 0.3,
|
|
||||||
pointRadius: 0,
|
|
||||||
borderWidth: 0,
|
|
||||||
borderJoinStyle: "round",
|
|
||||||
borderRadius: 4,
|
|
||||||
backgroundColor: "#c4a7e7",
|
|
||||||
barPercentage: 0.8,
|
|
||||||
categoryPercentage: 0.9,
|
|
||||||
fill: true,
|
|
||||||
clip: 8,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
aspectRatio: 5,
|
|
||||||
layout: {
|
|
||||||
padding: {
|
|
||||||
left: 0,
|
|
||||||
right: 8,
|
|
||||||
top: 0,
|
|
||||||
bottom: 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
scales: {
|
|
||||||
x: {
|
|
||||||
type: "time",
|
|
||||||
offset: false,
|
|
||||||
time: {
|
|
||||||
stepSize: 1,
|
|
||||||
unit: "day",
|
|
||||||
displayFormats: {
|
|
||||||
day: "M/d",
|
|
||||||
month: "Y/M",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
display: false,
|
|
||||||
},
|
|
||||||
ticks: {
|
|
||||||
display: false,
|
|
||||||
maxRotation: 0,
|
|
||||||
autoSkipPadding: 16,
|
|
||||||
},
|
|
||||||
min: getDate(chartLimit).getTime(),
|
|
||||||
},
|
|
||||||
y: {
|
|
||||||
position: "left",
|
|
||||||
suggestedMax: 10,
|
|
||||||
grid: {
|
|
||||||
display: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
interaction: {
|
|
||||||
intersect: false,
|
|
||||||
mode: "index",
|
|
||||||
},
|
|
||||||
elements: {
|
|
||||||
point: {
|
|
||||||
hoverRadius: 5,
|
|
||||||
hoverBorderWidth: 2,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: {
|
|
||||||
legend: {
|
|
||||||
display: false,
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
enabled: false,
|
|
||||||
mode: "index",
|
|
||||||
animation: {
|
|
||||||
duration: 0,
|
|
||||||
},
|
|
||||||
external: externalTooltipHandler2,
|
|
||||||
},
|
|
||||||
gradient,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: [chartVLine(vLineColor)],
|
|
||||||
});
|
|
||||||
|
|
||||||
fetching.value = false;
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" module>
|
|
||||||
.root {
|
|
||||||
&:global {
|
|
||||||
> .charts {
|
|
||||||
> .chart {
|
|
||||||
padding: 16px;
|
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
border-bottom: solid 0.5px var(--divider);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -17,40 +17,6 @@
|
||||||
<div class="subTitle">Top 10</div>
|
<div class="subTitle">Top 10</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="!fetching" class="items">
|
|
||||||
<div class="item _panel sub">
|
|
||||||
<div class="icon">
|
|
||||||
<i :class="icon('ph-download ph-xl', false)"></i>
|
|
||||||
</div>
|
|
||||||
<div class="body">
|
|
||||||
<div class="value">
|
|
||||||
{{ number(federationSubActive) }}
|
|
||||||
<MkNumberDiff
|
|
||||||
v-tooltip="i18n.ts.dayOverDayChanges"
|
|
||||||
class="diff"
|
|
||||||
:value="federationSubActiveDiff"
|
|
||||||
></MkNumberDiff>
|
|
||||||
</div>
|
|
||||||
<div class="label">Sub</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="item _panel pub">
|
|
||||||
<div class="icon">
|
|
||||||
<i :class="icon('ph-upload ph-xl', false)"></i>
|
|
||||||
</div>
|
|
||||||
<div class="body">
|
|
||||||
<div class="value">
|
|
||||||
{{ number(federationPubActive) }}
|
|
||||||
<MkNumberDiff
|
|
||||||
v-tooltip="i18n.ts.dayOverDayChanges"
|
|
||||||
class="diff"
|
|
||||||
:value="federationPubActiveDiff"
|
|
||||||
></MkNumberDiff>
|
|
||||||
</div>
|
|
||||||
<div class="label">Pub</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -59,32 +25,15 @@
|
||||||
import { onMounted, ref } from "vue";
|
import { onMounted, ref } from "vue";
|
||||||
import XPie from "./overview.pie.vue";
|
import XPie from "./overview.pie.vue";
|
||||||
import * as os from "@/os";
|
import * as os from "@/os";
|
||||||
import number from "@/filters/number";
|
|
||||||
import MkNumberDiff from "@/components/MkNumberDiff.vue";
|
|
||||||
import { i18n } from "@/i18n";
|
|
||||||
import { useChartTooltip } from "@/scripts/use-chart-tooltip";
|
import { useChartTooltip } from "@/scripts/use-chart-tooltip";
|
||||||
import icon from "@/scripts/icon";
|
|
||||||
|
|
||||||
const topSubInstancesForPie = ref<any>(null);
|
const topSubInstancesForPie = ref<any>(null);
|
||||||
const topPubInstancesForPie = ref<any>(null);
|
const topPubInstancesForPie = ref<any>(null);
|
||||||
const federationPubActive = ref<number | null>(null);
|
|
||||||
const federationPubActiveDiff = ref<number | null>(null);
|
|
||||||
const federationSubActive = ref<number | null>(null);
|
|
||||||
const federationSubActiveDiff = ref<number | null>(null);
|
|
||||||
const fetching = ref(true);
|
const fetching = ref(true);
|
||||||
|
|
||||||
useChartTooltip();
|
useChartTooltip();
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
const chart = await os.apiGet("charts/federation", {
|
|
||||||
limit: 2,
|
|
||||||
span: "day",
|
|
||||||
});
|
|
||||||
federationPubActive.value = chart.pubActive[0];
|
|
||||||
federationPubActiveDiff.value = chart.pubActive[0] - chart.pubActive[1];
|
|
||||||
federationSubActive.value = chart.subActive[0];
|
|
||||||
federationSubActiveDiff.value = chart.subActive[0] - chart.subActive[1];
|
|
||||||
|
|
||||||
os.apiGet("federation/stats", { limit: 10 }).then((res) => {
|
os.apiGet("federation/stats", { limit: 10 }).then((res) => {
|
||||||
topSubInstancesForPie.value = res.topSubInstances
|
topSubInstancesForPie.value = res.topSubInstances
|
||||||
.map((x) => ({
|
.map((x) => ({
|
||||||
|
|
|
@ -1,29 +1,11 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="_panel" :class="$style.root">
|
<div class="_panel" :class="$style.root">
|
||||||
<MkSelect v-model="src" style="margin: 0 0 12px 0" small>
|
<MkActiveUsersHeatmap />
|
||||||
<option value="notes">Posts</option>
|
|
||||||
<option value="active-users">Active users</option>
|
|
||||||
<option value="ap-requests-inbox-received">
|
|
||||||
Fediverse Requests: inboxReceived
|
|
||||||
</option>
|
|
||||||
<option value="ap-requests-deliver-succeeded">
|
|
||||||
Fediverse Requests: deliverSucceeded
|
|
||||||
</option>
|
|
||||||
<option value="ap-requests-deliver-failed">
|
|
||||||
Fediverse Requests: deliverFailed
|
|
||||||
</option>
|
|
||||||
</MkSelect>
|
|
||||||
<MkHeatmap :src="src" />
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from "vue";
|
import MkActiveUsersHeatmap from "@/components/MkActiveUsersHeatmap.vue";
|
||||||
|
|
||||||
import MkHeatmap from "@/components/MkHeatmap.vue";
|
|
||||||
import MkSelect from "@/components/form/select.vue";
|
|
||||||
|
|
||||||
const src = ref("notes");
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
|
|
|
@ -16,11 +16,6 @@
|
||||||
:value="stats.originalUsersCount"
|
:value="stats.originalUsersCount"
|
||||||
style="margin-right: 0.5em"
|
style="margin-right: 0.5em"
|
||||||
/>
|
/>
|
||||||
<MkNumberDiff
|
|
||||||
v-tooltip="i18n.ts.dayOverDayChanges"
|
|
||||||
class="diff"
|
|
||||||
:value="usersComparedToThePrevDay"
|
|
||||||
></MkNumberDiff>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="label">{{ i18n.ts.users }}</div>
|
<div class="label">{{ i18n.ts.users }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -35,11 +30,6 @@
|
||||||
:value="stats.originalNotesCount"
|
:value="stats.originalNotesCount"
|
||||||
style="margin-right: 0.5em"
|
style="margin-right: 0.5em"
|
||||||
/>
|
/>
|
||||||
<MkNumberDiff
|
|
||||||
v-tooltip="i18n.ts.dayOverDayChanges"
|
|
||||||
class="diff"
|
|
||||||
:value="notesComparedToThePrevDay"
|
|
||||||
></MkNumberDiff>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="label">{{ i18n.ts.notes }}</div>
|
<div class="label">{{ i18n.ts.notes }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -96,15 +86,12 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted, ref } from "vue";
|
import { onMounted, ref } from "vue";
|
||||||
import * as os from "@/os";
|
import * as os from "@/os";
|
||||||
import MkNumberDiff from "@/components/MkNumberDiff.vue";
|
|
||||||
import MkNumber from "@/components/MkNumber.vue";
|
import MkNumber from "@/components/MkNumber.vue";
|
||||||
import { i18n } from "@/i18n";
|
import { i18n } from "@/i18n";
|
||||||
import { defaultStore } from "@/store";
|
import { defaultStore } from "@/store";
|
||||||
import icon from "@/scripts/icon";
|
import icon from "@/scripts/icon";
|
||||||
|
|
||||||
const stats = ref(null);
|
const stats = ref(null);
|
||||||
const usersComparedToThePrevDay = ref<number>();
|
|
||||||
const notesComparedToThePrevDay = ref<number>();
|
|
||||||
const onlineUsersCount = ref(0);
|
const onlineUsersCount = ref(0);
|
||||||
const emojiCount = ref(0);
|
const emojiCount = ref(0);
|
||||||
const fetching = ref(true);
|
const fetching = ref(true);
|
||||||
|
@ -117,16 +104,6 @@ onMounted(async () => {
|
||||||
stats.value = _stats;
|
stats.value = _stats;
|
||||||
onlineUsersCount.value = _onlineUsersCount;
|
onlineUsersCount.value = _onlineUsersCount;
|
||||||
|
|
||||||
os.apiGet("charts/users", { limit: 2, span: "day" }).then((chart) => {
|
|
||||||
usersComparedToThePrevDay.value =
|
|
||||||
stats.value.originalUsersCount - chart.local.total[1];
|
|
||||||
});
|
|
||||||
|
|
||||||
os.apiGet("charts/notes", { limit: 2, span: "day" }).then((chart) => {
|
|
||||||
notesComparedToThePrevDay.value =
|
|
||||||
stats.value.originalNotesCount - chart.local.total[1];
|
|
||||||
});
|
|
||||||
|
|
||||||
os.api("meta", { detail: false }).then((meta) => {
|
os.api("meta", { detail: false }).then((meta) => {
|
||||||
emojiCount.value = meta.emojis.length;
|
emojiCount.value = meta.emojis.length;
|
||||||
});
|
});
|
||||||
|
|
|
@ -14,30 +14,14 @@
|
||||||
></span
|
></span
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<MkMiniChart v-if="chart" class="chart" :src="chart.inc" />
|
|
||||||
</MkA>
|
</MkA>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from "vue";
|
|
||||||
|
|
||||||
import { acct, type entities } from "firefish-js";
|
import { acct, type entities } from "firefish-js";
|
||||||
import MkMiniChart from "@/components/MkMiniChart.vue";
|
defineProps<{
|
||||||
import * as os from "@/os";
|
|
||||||
|
|
||||||
const props = defineProps<{
|
|
||||||
user: entities.User;
|
user: entities.User;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const chart = ref(null);
|
|
||||||
|
|
||||||
os.apiGet("charts/user/notes", {
|
|
||||||
userId: props.user.id,
|
|
||||||
limit: 16,
|
|
||||||
span: "day",
|
|
||||||
}).then((res) => {
|
|
||||||
chart.value = res;
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
|
|
|
@ -9,10 +9,6 @@
|
||||||
<MkFolder class="item">
|
<MkFolder class="item">
|
||||||
<template #header>Active users</template>
|
<template #header>Active users</template>
|
||||||
<XActiveUsers />
|
<XActiveUsers />
|
||||||
</MkFolder>
|
|
||||||
|
|
||||||
<MkFolder class="item">
|
|
||||||
<template #header>Heatmap</template>
|
|
||||||
<XHeatmap />
|
<XHeatmap />
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
|
@ -31,11 +27,6 @@
|
||||||
<XInstances />
|
<XInstances />
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
<MkFolder class="item">
|
|
||||||
<template #header>Fediverse Requests</template>
|
|
||||||
<XApRequests />
|
|
||||||
</MkFolder>
|
|
||||||
|
|
||||||
<MkFolder class="item">
|
<MkFolder class="item">
|
||||||
<template #header>New users</template>
|
<template #header>New users</template>
|
||||||
<XUsers />
|
<XUsers />
|
||||||
|
@ -71,7 +62,6 @@ import {
|
||||||
import XFederation from "./overview.federation.vue";
|
import XFederation from "./overview.federation.vue";
|
||||||
import XInstances from "./overview.instances.vue";
|
import XInstances from "./overview.instances.vue";
|
||||||
import XQueue from "./overview.queue.vue";
|
import XQueue from "./overview.queue.vue";
|
||||||
import XApRequests from "./overview.ap-requests.vue";
|
|
||||||
import XUsers from "./overview.users.vue";
|
import XUsers from "./overview.users.vue";
|
||||||
import XActiveUsers from "./overview.active-users.vue";
|
import XActiveUsers from "./overview.active-users.vue";
|
||||||
import XStats from "./overview.stats.vue";
|
import XStats from "./overview.stats.vue";
|
||||||
|
@ -89,10 +79,6 @@ const rootEl = shallowRef<HTMLElement>();
|
||||||
const serverInfo = ref<any>(null);
|
const serverInfo = ref<any>(null);
|
||||||
const topSubInstancesForPie = ref<any>(null);
|
const topSubInstancesForPie = ref<any>(null);
|
||||||
const topPubInstancesForPie = ref<any>(null);
|
const topPubInstancesForPie = ref<any>(null);
|
||||||
const federationPubActive = ref<number | null>(null);
|
|
||||||
const federationPubActiveDiff = ref<number | null>(null);
|
|
||||||
const federationSubActive = ref<number | null>(null);
|
|
||||||
const federationSubActiveDiff = ref<number | null>(null);
|
|
||||||
const newUsers = ref(null);
|
const newUsers = ref(null);
|
||||||
const activeInstances = shallowRef(null);
|
const activeInstances = shallowRef(null);
|
||||||
const queueStatsConnection = markRaw(stream.useChannel("queueStats"));
|
const queueStatsConnection = markRaw(stream.useChannel("queueStats"));
|
||||||
|
@ -108,13 +94,6 @@ onMounted(async () => {
|
||||||
magicGrid.listen();
|
magicGrid.listen();
|
||||||
*/
|
*/
|
||||||
|
|
||||||
os.apiGet("charts/federation", { limit: 2, span: "day" }).then((chart) => {
|
|
||||||
federationPubActive.value = chart.pubActive[0];
|
|
||||||
federationPubActiveDiff.value = chart.pubActive[0] - chart.pubActive[1];
|
|
||||||
federationSubActive.value = chart.subActive[0];
|
|
||||||
federationSubActiveDiff.value = chart.subActive[0] - chart.subActive[1];
|
|
||||||
});
|
|
||||||
|
|
||||||
os.apiGet("federation/stats", { limit: 10 }).then((res) => {
|
os.apiGet("federation/stats", { limit: 10 }).then((res) => {
|
||||||
topSubInstancesForPie.value = res.topSubInstances
|
topSubInstancesForPie.value = res.topSubInstances
|
||||||
.map((x) => ({
|
.map((x) => ({
|
||||||
|
|
|
@ -221,79 +221,6 @@
|
||||||
</FormSection>
|
</FormSection>
|
||||||
</div>
|
</div>
|
||||||
</swiper-slide>
|
</swiper-slide>
|
||||||
<swiper-slide>
|
|
||||||
<div class="_formRoot">
|
|
||||||
<div class="cmhjzshl">
|
|
||||||
<div class="selects">
|
|
||||||
<MkSelect
|
|
||||||
v-model="chartSrc"
|
|
||||||
style="margin: 0 10px 0 0; flex: 1"
|
|
||||||
>
|
|
||||||
<option value="instance-requests">
|
|
||||||
{{ i18n.ts._instanceCharts.requests }}
|
|
||||||
</option>
|
|
||||||
<option value="instance-users">
|
|
||||||
{{ i18n.ts._instanceCharts.users }}
|
|
||||||
</option>
|
|
||||||
<option value="instance-users-total">
|
|
||||||
{{ i18n.ts._instanceCharts.usersTotal }}
|
|
||||||
</option>
|
|
||||||
<option value="instance-notes">
|
|
||||||
{{ i18n.ts._instanceCharts.notes }}
|
|
||||||
</option>
|
|
||||||
<option value="instance-notes-total">
|
|
||||||
{{ i18n.ts._instanceCharts.notesTotal }}
|
|
||||||
</option>
|
|
||||||
<option value="instance-ff">
|
|
||||||
{{ i18n.ts._instanceCharts.ff }}
|
|
||||||
</option>
|
|
||||||
<option value="instance-ff-total">
|
|
||||||
{{ i18n.ts._instanceCharts.ffTotal }}
|
|
||||||
</option>
|
|
||||||
<option value="instance-drive-usage">
|
|
||||||
{{ i18n.ts._instanceCharts.cacheSize }}
|
|
||||||
</option>
|
|
||||||
<option value="instance-drive-usage-total">
|
|
||||||
{{
|
|
||||||
i18n.ts._instanceCharts
|
|
||||||
.cacheSizeTotal
|
|
||||||
}}
|
|
||||||
</option>
|
|
||||||
<option value="instance-drive-files">
|
|
||||||
{{ i18n.ts._instanceCharts.files }}
|
|
||||||
</option>
|
|
||||||
<option value="instance-drive-files-total">
|
|
||||||
{{ i18n.ts._instanceCharts.filesTotal }}
|
|
||||||
</option>
|
|
||||||
</MkSelect>
|
|
||||||
</div>
|
|
||||||
<div class="charts">
|
|
||||||
<div class="label">
|
|
||||||
{{ i18n.t("recentNHours", { n: 90 }) }}
|
|
||||||
</div>
|
|
||||||
<MkChart
|
|
||||||
class="chart"
|
|
||||||
:src="chartSrc"
|
|
||||||
span="hour"
|
|
||||||
:limit="90"
|
|
||||||
:args="{ host: host }"
|
|
||||||
:detailed="true"
|
|
||||||
></MkChart>
|
|
||||||
<div class="label">
|
|
||||||
{{ i18n.t("recentNDays", { n: 90 }) }}
|
|
||||||
</div>
|
|
||||||
<MkChart
|
|
||||||
class="chart"
|
|
||||||
:src="chartSrc"
|
|
||||||
span="day"
|
|
||||||
:limit="90"
|
|
||||||
:args="{ host: host }"
|
|
||||||
:detailed="true"
|
|
||||||
></MkChart>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</swiper-slide>
|
|
||||||
<swiper-slide>
|
<swiper-slide>
|
||||||
<div class="_formRoot">
|
<div class="_formRoot">
|
||||||
<MkPagination
|
<MkPagination
|
||||||
|
@ -339,7 +266,6 @@ import { computed, ref, watch } from "vue";
|
||||||
import { Virtual } from "swiper/modules";
|
import { Virtual } from "swiper/modules";
|
||||||
import { Swiper, SwiperSlide } from "swiper/vue";
|
import { Swiper, SwiperSlide } from "swiper/vue";
|
||||||
import type { entities } from "firefish-js";
|
import type { entities } from "firefish-js";
|
||||||
import MkChart from "@/components/MkChart.vue";
|
|
||||||
import MkObjectView from "@/components/MkObjectView.vue";
|
import MkObjectView from "@/components/MkObjectView.vue";
|
||||||
import FormLink from "@/components/form/link.vue";
|
import FormLink from "@/components/form/link.vue";
|
||||||
import MkLink from "@/components/MkLink.vue";
|
import MkLink from "@/components/MkLink.vue";
|
||||||
|
@ -375,17 +301,16 @@ const props = defineProps<{
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const tabs = ["overview"];
|
const tabs = ["overview"];
|
||||||
if (isAdmin) tabs.push("chart", "users", "raw");
|
if (isAdmin) tabs.push("users", "raw");
|
||||||
const tab = ref(tabs[0]);
|
const tab = ref(tabs[0]);
|
||||||
watch(tab, () => syncSlide(tabs.indexOf(tab.value)));
|
watch(tab, () => syncSlide(tabs.indexOf(tab.value)));
|
||||||
|
|
||||||
const chartSrc = ref("instance-requests");
|
|
||||||
const meta = ref<AugmentedInstanceMetadata | null>(null);
|
const meta = ref<AugmentedInstanceMetadata | null>(null);
|
||||||
const instance = ref<AugmentedInstance | null>(null);
|
const instance = ref<AugmentedInstance | null>(null);
|
||||||
const suspended = ref(false);
|
const suspended = ref(false);
|
||||||
const isBlocked = ref(false);
|
const isBlocked = ref(false);
|
||||||
const isSilenced = ref(false);
|
const isSilenced = ref(false);
|
||||||
const faviconUrl = ref(null);
|
const faviconUrl = ref<string | null>(null);
|
||||||
|
|
||||||
const usersPagination = {
|
const usersPagination = {
|
||||||
endpoint: isAdmin ? "admin/show-users" : ("users" as const),
|
endpoint: isAdmin ? "admin/show-users" : ("users" as const),
|
||||||
|
@ -486,11 +411,6 @@ const theTabs = [
|
||||||
|
|
||||||
if (isAdmin) {
|
if (isAdmin) {
|
||||||
theTabs.push(
|
theTabs.push(
|
||||||
{
|
|
||||||
key: "chart",
|
|
||||||
title: i18n.ts.charts,
|
|
||||||
icon: `${icon("ph-chart-bar")}`,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
key: "users",
|
key: "users",
|
||||||
title: i18n.ts.users,
|
title: i18n.ts.users,
|
||||||
|
@ -549,12 +469,5 @@ function syncSlide(index) {
|
||||||
display: flex;
|
display: flex;
|
||||||
margin: 0 0 16px 0;
|
margin: 0 0 16px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
> .charts {
|
|
||||||
> .label {
|
|
||||||
margin-bottom: 12px;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -17,20 +17,6 @@
|
||||||
</FormSplit>
|
</FormSplit>
|
||||||
</FormSection>
|
</FormSection>
|
||||||
|
|
||||||
<FormSection>
|
|
||||||
<template #label>{{ i18n.ts.statistics }}</template>
|
|
||||||
<MkChart
|
|
||||||
src="per-user-drive"
|
|
||||||
:args="{ user: $i }"
|
|
||||||
span="day"
|
|
||||||
:limit="7 * 5"
|
|
||||||
:bar="true"
|
|
||||||
:stacked="true"
|
|
||||||
:detailed="false"
|
|
||||||
:aspect-ratio="6"
|
|
||||||
/>
|
|
||||||
</FormSection>
|
|
||||||
|
|
||||||
<FormSection>
|
<FormSection>
|
||||||
<FormButton @click="chooseUploadFolder()">
|
<FormButton @click="chooseUploadFolder()">
|
||||||
{{ i18n.ts.uploadFolder }}
|
{{ i18n.ts.uploadFolder }}
|
||||||
|
@ -69,7 +55,6 @@ import FormSplit from "@/components/form/split.vue";
|
||||||
import * as os from "@/os";
|
import * as os from "@/os";
|
||||||
import bytes from "@/filters/bytes";
|
import bytes from "@/filters/bytes";
|
||||||
import { defaultStore } from "@/store";
|
import { defaultStore } from "@/store";
|
||||||
import MkChart from "@/components/MkChart.vue";
|
|
||||||
import { i18n } from "@/i18n";
|
import { i18n } from "@/i18n";
|
||||||
import { definePageMetadata } from "@/scripts/page-metadata";
|
import { definePageMetadata } from "@/scripts/page-metadata";
|
||||||
import { $i, isSignedIn } from "@/reactiveAccount";
|
import { $i, isSignedIn } from "@/reactiveAccount";
|
||||||
|
|
|
@ -330,44 +330,6 @@
|
||||||
</FormInput>
|
</FormInput>
|
||||||
</FormSection>
|
</FormSection>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="tab === 'chart'" class="_formRoot">
|
|
||||||
<div class="cmhjzshm">
|
|
||||||
<div class="selects">
|
|
||||||
<MkSelect
|
|
||||||
v-model="chartSrc"
|
|
||||||
style="margin: 0 10px 0 0; flex: 1"
|
|
||||||
>
|
|
||||||
<option value="per-user-notes">
|
|
||||||
{{ i18n.ts.notes }}
|
|
||||||
</option>
|
|
||||||
</MkSelect>
|
|
||||||
</div>
|
|
||||||
<div class="charts">
|
|
||||||
<div class="label">
|
|
||||||
{{ i18n.t("recentNHours", { n: 90 }) }}
|
|
||||||
</div>
|
|
||||||
<MkChart
|
|
||||||
class="chart"
|
|
||||||
:src="chartSrc"
|
|
||||||
span="hour"
|
|
||||||
:limit="90"
|
|
||||||
:args="{ user, withoutAll: true }"
|
|
||||||
:detailed="true"
|
|
||||||
></MkChart>
|
|
||||||
<div class="label">
|
|
||||||
{{ i18n.t("recentNDays", { n: 90 }) }}
|
|
||||||
</div>
|
|
||||||
<MkChart
|
|
||||||
class="chart"
|
|
||||||
:src="chartSrc"
|
|
||||||
span="day"
|
|
||||||
:limit="90"
|
|
||||||
:args="{ user, withoutAll: true }"
|
|
||||||
:detailed="true"
|
|
||||||
></MkChart>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div v-else-if="tab === 'raw'" class="_formRoot">
|
<div v-else-if="tab === 'raw'" class="_formRoot">
|
||||||
<MkObjectView v-if="info && isAdmin" tall :value="info">
|
<MkObjectView v-if="info && isAdmin" tall :value="info">
|
||||||
</MkObjectView>
|
</MkObjectView>
|
||||||
|
@ -382,7 +344,6 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, ref, watch } from "vue";
|
import { computed, ref, watch } from "vue";
|
||||||
import { acct, type entities } from "firefish-js";
|
import { acct, type entities } from "firefish-js";
|
||||||
import MkChart from "@/components/MkChart.vue";
|
|
||||||
import MkObjectView from "@/components/MkObjectView.vue";
|
import MkObjectView from "@/components/MkObjectView.vue";
|
||||||
import FormTextarea from "@/components/form/textarea.vue";
|
import FormTextarea from "@/components/form/textarea.vue";
|
||||||
import FormSwitch from "@/components/form/switch.vue";
|
import FormSwitch from "@/components/form/switch.vue";
|
||||||
|
@ -410,7 +371,6 @@ const props = defineProps<{
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const tab = ref("overview");
|
const tab = ref("overview");
|
||||||
const chartSrc = ref("per-user-notes");
|
|
||||||
const user = ref<null | entities.UserDetailed>();
|
const user = ref<null | entities.UserDetailed>();
|
||||||
const init = ref<ReturnType<typeof createFetcher>>();
|
const init = ref<ReturnType<typeof createFetcher>>();
|
||||||
const info = ref();
|
const info = ref();
|
||||||
|
@ -680,11 +640,6 @@ const headerTabs = computed(() =>
|
||||||
icon: `${icon("ph-shield")}`,
|
icon: `${icon("ph-shield")}`,
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
{
|
|
||||||
key: "chart",
|
|
||||||
title: i18n.ts.charts,
|
|
||||||
icon: `${icon("ph-chart-bar")}`,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
key: "raw",
|
key: "raw",
|
||||||
title: "Raw",
|
title: "Raw",
|
||||||
|
@ -772,20 +727,6 @@ definePageMetadata(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.cmhjzshm {
|
|
||||||
> .selects {
|
|
||||||
display: flex;
|
|
||||||
margin: 0 0 16px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .charts {
|
|
||||||
> .label {
|
|
||||||
margin-bottom: 12px;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
|
|
|
@ -347,11 +347,6 @@
|
||||||
>
|
>
|
||||||
<template v-if="narrow">
|
<template v-if="narrow">
|
||||||
<XPhotos :key="user.id" :user="user" />
|
<XPhotos :key="user.id" :user="user" />
|
||||||
<!-- <XActivity
|
|
||||||
:key="user.id"
|
|
||||||
:user="user"
|
|
||||||
style="margin-top: var(--margin)"
|
|
||||||
/> -->
|
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
@ -360,11 +355,6 @@
|
||||||
</div>
|
</div>
|
||||||
<div v-if="!narrow" class="sub">
|
<div v-if="!narrow" class="sub">
|
||||||
<XPhotos :key="user.id" :user="user" />
|
<XPhotos :key="user.id" :user="user" />
|
||||||
<XActivity
|
|
||||||
:key="user.id"
|
|
||||||
:user="user"
|
|
||||||
style="margin-top: var(--margin)"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</MkSpacer>
|
</MkSpacer>
|
||||||
|
@ -399,7 +389,6 @@ import { host } from "@/config";
|
||||||
import icon from "@/scripts/icon";
|
import icon from "@/scripts/icon";
|
||||||
|
|
||||||
const XPhotos = defineAsyncComponent(() => import("./index.photos.vue"));
|
const XPhotos = defineAsyncComponent(() => import("./index.photos.vue"));
|
||||||
const XActivity = defineAsyncComponent(() => import("./index.activity.vue"));
|
|
||||||
|
|
||||||
const hideFollowButton = defaultStore.state.hideFollowButtons;
|
const hideFollowButton = defaultStore.state.hideFollowButtons;
|
||||||
|
|
||||||
|
|
|
@ -1,74 +0,0 @@
|
||||||
<template>
|
|
||||||
<MkContainer>
|
|
||||||
<template #header
|
|
||||||
><i :class="icon('ph-chart-bar')" style="margin-right: 0.5em"></i
|
|
||||||
>{{ i18n.ts.activity }}</template
|
|
||||||
>
|
|
||||||
<template #func>
|
|
||||||
<button class="_button" @click="showMenu">
|
|
||||||
<i :class="icon('ph-dots-three-outline')"></i>
|
|
||||||
</button>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<div style="padding: 8px">
|
|
||||||
<MkChart
|
|
||||||
:src="chartSrc"
|
|
||||||
:args="{ user, withoutAll: true }"
|
|
||||||
span="day"
|
|
||||||
:limit="limit"
|
|
||||||
:bar="true"
|
|
||||||
:stacked="true"
|
|
||||||
:detailed="false"
|
|
||||||
:aspect-ratio="5"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</MkContainer>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { ref } from "vue";
|
|
||||||
|
|
||||||
import type { entities } from "firefish-js";
|
|
||||||
import MkContainer from "@/components/MkContainer.vue";
|
|
||||||
import MkChart from "@/components/MkChart.vue";
|
|
||||||
import * as os from "@/os";
|
|
||||||
import { i18n } from "@/i18n";
|
|
||||||
import icon from "@/scripts/icon";
|
|
||||||
|
|
||||||
withDefaults(
|
|
||||||
defineProps<{
|
|
||||||
user: entities.User;
|
|
||||||
limit?: number;
|
|
||||||
}>(),
|
|
||||||
{
|
|
||||||
limit: 50,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const chartSrc = ref("per-user-notes");
|
|
||||||
|
|
||||||
function showMenu(ev: MouseEvent) {
|
|
||||||
os.popupMenu(
|
|
||||||
[
|
|
||||||
{
|
|
||||||
text: i18n.ts.notes,
|
|
||||||
active: true,
|
|
||||||
action: () => {
|
|
||||||
chartSrc.value = "per-user-notes";
|
|
||||||
},
|
|
||||||
} /*, {
|
|
||||||
text: i18n.ts.following,
|
|
||||||
action: () => {
|
|
||||||
chartSrc = 'per-user-following';
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
text: i18n.ts.followers,
|
|
||||||
action: () => {
|
|
||||||
chartSrc = 'per-user-followers';
|
|
||||||
}
|
|
||||||
} */,
|
|
||||||
],
|
|
||||||
ev.currentTarget ?? ev.target,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
</script>
|
|
|
@ -1,102 +0,0 @@
|
||||||
<template>
|
|
||||||
<svg viewBox="0 0 21 7">
|
|
||||||
<rect
|
|
||||||
v-for="record in activity"
|
|
||||||
class="day"
|
|
||||||
width="1"
|
|
||||||
height="1"
|
|
||||||
:x="record.x"
|
|
||||||
:y="record.date.weekday"
|
|
||||||
rx="1"
|
|
||||||
ry="1"
|
|
||||||
fill="transparent"
|
|
||||||
>
|
|
||||||
<title>
|
|
||||||
{{ record.date.year }}/{{ record.date.month + 1 }}/{{
|
|
||||||
record.date.day
|
|
||||||
}}
|
|
||||||
</title>
|
|
||||||
</rect>
|
|
||||||
<rect
|
|
||||||
v-for="record in activity"
|
|
||||||
class="day"
|
|
||||||
:width="record.v"
|
|
||||||
:height="record.v"
|
|
||||||
:x="record.x + (1 - record.v) / 2"
|
|
||||||
:y="record.date.weekday + (1 - record.v) / 2"
|
|
||||||
rx="1"
|
|
||||||
ry="1"
|
|
||||||
:fill="record.color"
|
|
||||||
style="pointer-events: none"
|
|
||||||
/>
|
|
||||||
<rect
|
|
||||||
class="today"
|
|
||||||
width="1"
|
|
||||||
height="1"
|
|
||||||
:x="activity[0].x"
|
|
||||||
:y="activity[0].date.weekday"
|
|
||||||
rx="1"
|
|
||||||
ry="1"
|
|
||||||
fill="none"
|
|
||||||
stroke-width="0.1"
|
|
||||||
stroke="#eb6f92"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
const props = defineProps<{
|
|
||||||
activity: any[];
|
|
||||||
}>();
|
|
||||||
|
|
||||||
for (const d of props.activity) {
|
|
||||||
d.total = d.notes + d.replies + d.renotes;
|
|
||||||
}
|
|
||||||
const peak = Math.max(...props.activity.map((d) => d.total));
|
|
||||||
|
|
||||||
const now = new Date();
|
|
||||||
const year = now.getFullYear();
|
|
||||||
const month = now.getMonth();
|
|
||||||
const day = now.getDate();
|
|
||||||
|
|
||||||
let x = 20;
|
|
||||||
props.activity.slice().forEach((d, i) => {
|
|
||||||
d.x = x;
|
|
||||||
|
|
||||||
const date = new Date(year, month, day - i);
|
|
||||||
d.date = {
|
|
||||||
year: date.getFullYear(),
|
|
||||||
month: date.getMonth(),
|
|
||||||
day: date.getDate(),
|
|
||||||
weekday: date.getDay(),
|
|
||||||
};
|
|
||||||
|
|
||||||
d.v = peak === 0 ? 0 : d.total / (peak / 2);
|
|
||||||
if (d.v > 1) d.v = 1;
|
|
||||||
const ch = d.date.weekday === 0 || d.date.weekday === 6 ? 275 : 170;
|
|
||||||
const cs = d.v * 100;
|
|
||||||
const cl = 15 + (1 - d.v) * 80;
|
|
||||||
d.color = `hsl(${ch}, ${cs}%, ${cl}%)`;
|
|
||||||
|
|
||||||
if (d.date.weekday === 0) x--;
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
svg {
|
|
||||||
display: block;
|
|
||||||
padding: 16px;
|
|
||||||
width: 100%;
|
|
||||||
box-sizing: border-box;
|
|
||||||
|
|
||||||
> rect {
|
|
||||||
transform-origin: center;
|
|
||||||
|
|
||||||
&.day {
|
|
||||||
&:hover {
|
|
||||||
fill: rgba(#000, 0.05);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,136 +0,0 @@
|
||||||
<template>
|
|
||||||
<svg
|
|
||||||
:viewBox="`0 0 ${viewBoxX} ${viewBoxY}`"
|
|
||||||
@mousedown.prevent="onMousedown"
|
|
||||||
>
|
|
||||||
<polyline
|
|
||||||
:points="pointsNote"
|
|
||||||
fill="none"
|
|
||||||
stroke-width="1"
|
|
||||||
stroke="#c4a7e7"
|
|
||||||
/>
|
|
||||||
<polyline
|
|
||||||
:points="pointsReply"
|
|
||||||
fill="none"
|
|
||||||
stroke-width="1"
|
|
||||||
stroke="#eb6f92"
|
|
||||||
/>
|
|
||||||
<polyline
|
|
||||||
:points="pointsRenote"
|
|
||||||
fill="none"
|
|
||||||
stroke-width="1"
|
|
||||||
stroke="#ebbcba"
|
|
||||||
/>
|
|
||||||
<polyline
|
|
||||||
:points="pointsTotal"
|
|
||||||
fill="none"
|
|
||||||
stroke-width="1"
|
|
||||||
stroke="#6e6a86"
|
|
||||||
stroke-dasharray="2 2"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { ref } from "vue";
|
|
||||||
|
|
||||||
const props = defineProps<{
|
|
||||||
activity: any[];
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const viewBoxX: number = ref(147);
|
|
||||||
const viewBoxY: number = ref(60);
|
|
||||||
const zoom: number = ref(1);
|
|
||||||
const pos: number = ref(0);
|
|
||||||
const pointsNote: any = ref(null);
|
|
||||||
const pointsReply: any = ref(null);
|
|
||||||
const pointsRenote: any = ref(null);
|
|
||||||
const pointsTotal: any = ref(null);
|
|
||||||
|
|
||||||
function dragListen(fn) {
|
|
||||||
window.addEventListener("mousemove", fn);
|
|
||||||
window.addEventListener("mouseleave", dragClear.bind(null, fn));
|
|
||||||
window.addEventListener("mouseup", dragClear.bind(null, fn));
|
|
||||||
}
|
|
||||||
|
|
||||||
function dragClear(fn) {
|
|
||||||
window.removeEventListener("mousemove", fn);
|
|
||||||
window.removeEventListener("mouseleave", dragClear);
|
|
||||||
window.removeEventListener("mouseup", dragClear);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onMousedown(ev) {
|
|
||||||
const clickX = ev.clientX;
|
|
||||||
const clickY = ev.clientY;
|
|
||||||
const baseZoom = zoom.value;
|
|
||||||
const basePos = pos.value;
|
|
||||||
|
|
||||||
// 動かした時
|
|
||||||
dragListen((me) => {
|
|
||||||
const moveLeft = me.clientX - clickX;
|
|
||||||
const moveTop = me.clientY - clickY;
|
|
||||||
|
|
||||||
zoom.value = Math.max(1, baseZoom + -moveTop / 20);
|
|
||||||
pos.value = Math.min(0, basePos + moveLeft);
|
|
||||||
if (
|
|
||||||
pos.value <
|
|
||||||
-((props.activity.length - 1) * zoom.value - viewBoxX.value)
|
|
||||||
)
|
|
||||||
pos.value = -(
|
|
||||||
(props.activity.length - 1) * zoom.value -
|
|
||||||
viewBoxX.value
|
|
||||||
);
|
|
||||||
|
|
||||||
render();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function render() {
|
|
||||||
const peak = Math.max(...props.activity.map((d) => d.total));
|
|
||||||
if (peak !== 0) {
|
|
||||||
const activity = props.activity.slice().reverse();
|
|
||||||
pointsNote.value = activity
|
|
||||||
.map(
|
|
||||||
(d, i) =>
|
|
||||||
`${i * zoom.value + pos.value},${
|
|
||||||
(1 - d.notes / peak) * viewBoxY.value
|
|
||||||
}`,
|
|
||||||
)
|
|
||||||
.join(" ");
|
|
||||||
pointsReply.value = activity
|
|
||||||
.map(
|
|
||||||
(d, i) =>
|
|
||||||
`${i * zoom.value + pos.value},${
|
|
||||||
(1 - d.replies / peak) * viewBoxY.value
|
|
||||||
}`,
|
|
||||||
)
|
|
||||||
.join(" ");
|
|
||||||
pointsRenote.value = activity
|
|
||||||
.map(
|
|
||||||
(d, i) =>
|
|
||||||
`${i * zoom.value + pos.value},${
|
|
||||||
(1 - d.renotes / peak) * viewBoxY.value
|
|
||||||
}`,
|
|
||||||
)
|
|
||||||
.join(" ");
|
|
||||||
pointsTotal.value = activity
|
|
||||||
.map(
|
|
||||||
(d, i) =>
|
|
||||||
`${i * zoom.value + pos.value},${
|
|
||||||
(1 - d.total / peak) * viewBoxY.value
|
|
||||||
}`,
|
|
||||||
)
|
|
||||||
.join(" ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
svg {
|
|
||||||
display: block;
|
|
||||||
padding: 16px;
|
|
||||||
width: 100%;
|
|
||||||
box-sizing: border-box;
|
|
||||||
cursor: all-scroll;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,121 +0,0 @@
|
||||||
<template>
|
|
||||||
<MkContainer
|
|
||||||
:show-header="widgetProps.showHeader"
|
|
||||||
:naked="widgetProps.transparent"
|
|
||||||
class="mkw-activity"
|
|
||||||
>
|
|
||||||
<template #header
|
|
||||||
><i :class="icon('ph-chart-bar')"></i
|
|
||||||
>{{ i18n.ts._widgets.activity }}</template
|
|
||||||
>
|
|
||||||
<template #func
|
|
||||||
><button
|
|
||||||
v-if="!widgetProps.newStyle"
|
|
||||||
class="_button"
|
|
||||||
@click="toggleView()"
|
|
||||||
>
|
|
||||||
<i :class="icon('ph-sort-ascending')"></i></button
|
|
||||||
></template>
|
|
||||||
|
|
||||||
<div v-if="widgetProps.newStyle">
|
|
||||||
<MkHeatmap src="my-notes" />
|
|
||||||
</div>
|
|
||||||
<div v-else>
|
|
||||||
<MkLoading v-if="fetching" />
|
|
||||||
<template v-else>
|
|
||||||
<XCalendar
|
|
||||||
v-show="widgetProps.view === 0"
|
|
||||||
:activity="[].concat(activity)"
|
|
||||||
/>
|
|
||||||
<XChart
|
|
||||||
v-show="widgetProps.view === 1"
|
|
||||||
:activity="[].concat(activity)"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
</MkContainer>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { ref } from "vue";
|
|
||||||
import type { Widget, WidgetComponentExpose } from "./widget";
|
|
||||||
import { useWidgetPropsManager } from "./widget";
|
|
||||||
import XCalendar from "./activity.calendar.vue";
|
|
||||||
import XChart from "./activity.chart.vue";
|
|
||||||
import MkHeatmap from "@/components/MkHeatmap.vue";
|
|
||||||
import type { GetFormResultType } from "@/scripts/form";
|
|
||||||
import * as os from "@/os";
|
|
||||||
import MkContainer from "@/components/MkContainer.vue";
|
|
||||||
import { $i } from "@/reactiveAccount";
|
|
||||||
import { i18n } from "@/i18n";
|
|
||||||
import icon from "@/scripts/icon";
|
|
||||||
|
|
||||||
const name = "activity";
|
|
||||||
|
|
||||||
const widgetPropsDef = {
|
|
||||||
newStyle: {
|
|
||||||
type: "boolean" as const,
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
showHeader: {
|
|
||||||
type: "boolean" as const,
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
transparent: {
|
|
||||||
type: "boolean" as const,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
view: {
|
|
||||||
type: "number" as const,
|
|
||||||
default: 0,
|
|
||||||
hidden: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
type WidgetProps = GetFormResultType<typeof widgetPropsDef>;
|
|
||||||
|
|
||||||
// 現時点ではvueの制限によりimportしたtypeをジェネリックに渡せない
|
|
||||||
// const props = defineProps<WidgetComponentProps<WidgetProps>>();
|
|
||||||
// const emit = defineEmits<WidgetComponentEmits<WidgetProps>>();
|
|
||||||
const props = defineProps<{ widget?: Widget<WidgetProps> }>();
|
|
||||||
const emit = defineEmits<{ (ev: "updateProps", props: WidgetProps) }>();
|
|
||||||
|
|
||||||
const { widgetProps, configure, save } = useWidgetPropsManager(
|
|
||||||
name,
|
|
||||||
widgetPropsDef,
|
|
||||||
props,
|
|
||||||
emit,
|
|
||||||
);
|
|
||||||
|
|
||||||
const activity = ref(null);
|
|
||||||
const fetching = ref(true);
|
|
||||||
|
|
||||||
const toggleView = () => {
|
|
||||||
if (widgetProps.view === 1) {
|
|
||||||
widgetProps.view = 0;
|
|
||||||
} else {
|
|
||||||
widgetProps.view++;
|
|
||||||
}
|
|
||||||
save();
|
|
||||||
};
|
|
||||||
|
|
||||||
os.apiGet("charts/user/notes", {
|
|
||||||
userId: $i.id,
|
|
||||||
span: "day",
|
|
||||||
limit: 7 * 21,
|
|
||||||
}).then((res) => {
|
|
||||||
activity.value = res.diffs.normal.map((_, i) => ({
|
|
||||||
total: res.diffs.normal[i] + res.diffs.reply[i] + res.diffs.renote[i],
|
|
||||||
notes: res.diffs.normal[i],
|
|
||||||
replies: res.diffs.reply[i],
|
|
||||||
renotes: res.diffs.renote[i],
|
|
||||||
}));
|
|
||||||
fetching.value = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
defineExpose<WidgetComponentExpose>({
|
|
||||||
name,
|
|
||||||
configure,
|
|
||||||
id: props.widget ? props.widget.id : null,
|
|
||||||
});
|
|
||||||
</script>
|
|
|
@ -37,10 +37,6 @@
|
||||||
{{ instance.softwareVersion }}
|
{{ instance.softwareVersion }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<MkMiniChart
|
|
||||||
class="chart"
|
|
||||||
:src="charts[i].requests.received"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</transition-group>
|
</transition-group>
|
||||||
</div>
|
</div>
|
||||||
|
@ -53,7 +49,6 @@ import type { Widget, WidgetComponentExpose } from "./widget";
|
||||||
import { useWidgetPropsManager } from "./widget";
|
import { useWidgetPropsManager } from "./widget";
|
||||||
import type { GetFormResultType } from "@/scripts/form";
|
import type { GetFormResultType } from "@/scripts/form";
|
||||||
import MkContainer from "@/components/MkContainer.vue";
|
import MkContainer from "@/components/MkContainer.vue";
|
||||||
import MkMiniChart from "@/components/MkMiniChart.vue";
|
|
||||||
import * as os from "@/os";
|
import * as os from "@/os";
|
||||||
import { useInterval } from "@/scripts/use-interval";
|
import { useInterval } from "@/scripts/use-interval";
|
||||||
import { i18n } from "@/i18n";
|
import { i18n } from "@/i18n";
|
||||||
|
@ -90,7 +85,6 @@ const { widgetProps, configure } = useWidgetPropsManager(
|
||||||
);
|
);
|
||||||
|
|
||||||
const instances = ref([]);
|
const instances = ref([]);
|
||||||
const charts = ref([]);
|
|
||||||
const fetching = ref(true);
|
const fetching = ref(true);
|
||||||
|
|
||||||
const fetch = async () => {
|
const fetch = async () => {
|
||||||
|
@ -98,17 +92,7 @@ const fetch = async () => {
|
||||||
sort: "+lastCommunicatedAt",
|
sort: "+lastCommunicatedAt",
|
||||||
limit: 5,
|
limit: 5,
|
||||||
});
|
});
|
||||||
const fetchedCharts = await Promise.all(
|
|
||||||
fetchedInstances.map((i) =>
|
|
||||||
os.apiGet("charts/instance", {
|
|
||||||
host: i.host,
|
|
||||||
limit: 16,
|
|
||||||
span: "hour",
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
instances.value = fetchedInstances;
|
instances.value = fetchedInstances;
|
||||||
charts.value = fetchedCharts;
|
|
||||||
fetching.value = false;
|
fetching.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -34,10 +34,6 @@ export default function (app: App) {
|
||||||
"MkwClock",
|
"MkwClock",
|
||||||
defineAsyncComponent(() => import("./clock.vue")),
|
defineAsyncComponent(() => import("./clock.vue")),
|
||||||
);
|
);
|
||||||
app.component(
|
|
||||||
"MkwActivity",
|
|
||||||
defineAsyncComponent(() => import("./activity.vue")),
|
|
||||||
);
|
|
||||||
app.component(
|
app.component(
|
||||||
"MkwPhotos",
|
"MkwPhotos",
|
||||||
defineAsyncComponent(() => import("./photos.vue")),
|
defineAsyncComponent(() => import("./photos.vue")),
|
||||||
|
@ -106,7 +102,6 @@ export const widgets = [
|
||||||
"rssTicker",
|
"rssTicker",
|
||||||
"trends",
|
"trends",
|
||||||
"clock",
|
"clock",
|
||||||
"activity",
|
|
||||||
"photos",
|
"photos",
|
||||||
"digitalClock",
|
"digitalClock",
|
||||||
"unixClock",
|
"unixClock",
|
||||||
|
|
|
@ -216,185 +216,6 @@ export type Endpoints = {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
"charts/drive": {
|
|
||||||
req: { span: "day" | "hour"; limit?: number; offset?: number | null };
|
|
||||||
res: {
|
|
||||||
local: {
|
|
||||||
decCount: number[];
|
|
||||||
decSize: number[];
|
|
||||||
incCount: number[];
|
|
||||||
incSize: number[];
|
|
||||||
totalCount: number[];
|
|
||||||
totalSize: number[];
|
|
||||||
};
|
|
||||||
remote: {
|
|
||||||
decCount: number[];
|
|
||||||
decSize: number[];
|
|
||||||
incCount: number[];
|
|
||||||
incSize: number[];
|
|
||||||
totalCount: number[];
|
|
||||||
totalSize: number[];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
"charts/federation": {
|
|
||||||
req: { span: "day" | "hour"; limit?: number; offset?: number | null };
|
|
||||||
res: {
|
|
||||||
instance: {
|
|
||||||
dec: number[];
|
|
||||||
inc: number[];
|
|
||||||
total: number[];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
"charts/hashtag": {
|
|
||||||
req: { span: "day" | "hour"; limit?: number; offset?: number | null };
|
|
||||||
res: TODO;
|
|
||||||
};
|
|
||||||
"charts/instance": {
|
|
||||||
req: {
|
|
||||||
span: "day" | "hour";
|
|
||||||
limit?: number;
|
|
||||||
offset?: number | null;
|
|
||||||
host: string;
|
|
||||||
};
|
|
||||||
res: {
|
|
||||||
drive: {
|
|
||||||
decFiles: number[];
|
|
||||||
decUsage: number[];
|
|
||||||
incFiles: number[];
|
|
||||||
incUsage: number[];
|
|
||||||
totalFiles: number[];
|
|
||||||
totalUsage: number[];
|
|
||||||
};
|
|
||||||
followers: {
|
|
||||||
dec: number[];
|
|
||||||
inc: number[];
|
|
||||||
total: number[];
|
|
||||||
};
|
|
||||||
following: {
|
|
||||||
dec: number[];
|
|
||||||
inc: number[];
|
|
||||||
total: number[];
|
|
||||||
};
|
|
||||||
notes: {
|
|
||||||
dec: number[];
|
|
||||||
inc: number[];
|
|
||||||
total: number[];
|
|
||||||
diffs: {
|
|
||||||
normal: number[];
|
|
||||||
renote: number[];
|
|
||||||
reply: number[];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
requests: {
|
|
||||||
failed: number[];
|
|
||||||
received: number[];
|
|
||||||
succeeded: number[];
|
|
||||||
};
|
|
||||||
users: {
|
|
||||||
dec: number[];
|
|
||||||
inc: number[];
|
|
||||||
total: number[];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
"charts/network": {
|
|
||||||
req: { span: "day" | "hour"; limit?: number; offset?: number | null };
|
|
||||||
res: TODO;
|
|
||||||
};
|
|
||||||
"charts/notes": {
|
|
||||||
req: { span: "day" | "hour"; limit?: number; offset?: number | null };
|
|
||||||
res: {
|
|
||||||
local: {
|
|
||||||
dec: number[];
|
|
||||||
inc: number[];
|
|
||||||
total: number[];
|
|
||||||
diffs: {
|
|
||||||
normal: number[];
|
|
||||||
renote: number[];
|
|
||||||
reply: number[];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
remote: {
|
|
||||||
dec: number[];
|
|
||||||
inc: number[];
|
|
||||||
total: number[];
|
|
||||||
diffs: {
|
|
||||||
normal: number[];
|
|
||||||
renote: number[];
|
|
||||||
reply: number[];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
"charts/user/drive": {
|
|
||||||
req: {
|
|
||||||
span: "day" | "hour";
|
|
||||||
limit?: number;
|
|
||||||
offset?: number | null;
|
|
||||||
userId: User["id"];
|
|
||||||
};
|
|
||||||
res: {
|
|
||||||
decCount: number[];
|
|
||||||
decSize: number[];
|
|
||||||
incCount: number[];
|
|
||||||
incSize: number[];
|
|
||||||
totalCount: number[];
|
|
||||||
totalSize: number[];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
"charts/user/following": {
|
|
||||||
req: {
|
|
||||||
span: "day" | "hour";
|
|
||||||
limit?: number;
|
|
||||||
offset?: number | null;
|
|
||||||
userId: User["id"];
|
|
||||||
};
|
|
||||||
res: TODO;
|
|
||||||
};
|
|
||||||
"charts/user/notes": {
|
|
||||||
req: {
|
|
||||||
span: "day" | "hour";
|
|
||||||
limit?: number;
|
|
||||||
offset?: number | null;
|
|
||||||
userId: User["id"];
|
|
||||||
};
|
|
||||||
res: {
|
|
||||||
dec: number[];
|
|
||||||
inc: number[];
|
|
||||||
total: number[];
|
|
||||||
diffs: {
|
|
||||||
normal: number[];
|
|
||||||
renote: number[];
|
|
||||||
reply: number[];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
"charts/user/reactions": {
|
|
||||||
req: {
|
|
||||||
span: "day" | "hour";
|
|
||||||
limit?: number;
|
|
||||||
offset?: number | null;
|
|
||||||
userId: User["id"];
|
|
||||||
};
|
|
||||||
res: TODO;
|
|
||||||
};
|
|
||||||
"charts/users": {
|
|
||||||
req: { span: "day" | "hour"; limit?: number; offset?: number | null };
|
|
||||||
res: {
|
|
||||||
local: {
|
|
||||||
dec: number[];
|
|
||||||
inc: number[];
|
|
||||||
total: number[];
|
|
||||||
};
|
|
||||||
remote: {
|
|
||||||
dec: number[];
|
|
||||||
inc: number[];
|
|
||||||
total: number[];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// clips
|
// clips
|
||||||
"clips/add-note": { req: TODO; res: TODO };
|
"clips/add-note": { req: TODO; res: TODO };
|
||||||
|
|
Loading…
Reference in a new issue