Merge branch 'develop' into refactor/push-notification

This commit is contained in:
naskya 2024-05-08 06:11:52 +09:00
commit c3374b4914
No known key found for this signature in database
GPG Key ID: 712D413B3A9FED5C
8 changed files with 96 additions and 49 deletions

View File

@ -12,6 +12,11 @@ workflow:
when: always
- if: $CI_MERGE_REQUEST_PROJECT_PATH == 'firefish/firefish'
when: always
- if: $CI_PROJECT_PATH != 'firefish/firefish'
changes:
paths:
- .gitlab-ci.yml
when: never
- when: never
cache:
@ -56,9 +61,11 @@ build_test:
- if: $CI_PIPELINE_SOURCE == 'push' || $CI_PIPELINE_SOURCE == 'merge_request_event'
changes:
paths:
- packages/**/*
- packages/backend/*
- packages/backend-rs/*
- packages/macro-rs/*
- packages/megalodon/*
- scripts/**/*
- locales/**/*
- package.json
- pnpm-lock.yaml
- Cargo.toml
@ -68,6 +75,33 @@ build_test:
- pnpm run build:debug
- pnpm run migrate
client_build_test:
stage: test
rules:
- if: $CI_PIPELINE_SOURCE == 'push' || $CI_PIPELINE_SOURCE == 'merge_request_event'
changes:
paths:
- packages/client/*
- packages/firefish-js/*
- packages/sw/*
- scripts/**/*
- locales/**/*
- package.json
- pnpm-lock.yaml
- if: $CI_PIPELINE_SOURCE == 'push' || $CI_PIPELINE_SOURCE == 'merge_request_event'
changes:
paths:
- packages/backend/*
- packages/backend-rs/*
- packages/macro-rs/*
- packages/megalodon/*
- Cargo.toml
- Cargo.lock
when: never
script:
- pnpm install --frozen-lockfile
- pnpm --filter 'firefish-js' --filter 'client' --filter 'sw' run build:debug
container_image_build:
stage: build
image: docker.io/debian:bookworm-slim
@ -90,8 +124,21 @@ container_image_build:
- apt-get install -y --no-install-recommends buildah ca-certificates fuse-overlayfs
- buildah login --username "${CI_REGISTRY_USER}" --password "${CI_REGISTRY_PASSWORD}" "${CI_REGISTRY}"
- export IMAGE_TAG="${CI_REGISTRY}/${CI_PROJECT_PATH}/develop:not-for-production"
- export IMAGE_CACHE="${CI_REGISTRY}/${CI_PROJECT_PATH}/develop/cache"
script:
- buildah build --isolation chroot --device /dev/fuse:rw --security-opt seccomp=unconfined --security-opt apparmor=unconfined --cap-add all --tag "${IMAGE_TAG}" --platform linux/amd64 .
- |-
buildah build \
--isolation chroot \
--device /dev/fuse:rw \
--security-opt seccomp=unconfined \
--security-opt apparmor=unconfined \
--cap-add all \
--platform linux/amd64 \
--layers \
--cache-to "${IMAGE_CACHE}" \
--cache-from "${IMAGE_CACHE}" \
--tag "${IMAGE_TAG}" \
.
- buildah inspect "${IMAGE_TAG}"
- buildah push "${IMAGE_TAG}"
@ -119,7 +166,7 @@ cargo_unit_test:
cargo_clippy:
stage: test
rules:
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
- if: $CI_PIPELINE_SOURCE == 'merge_request_event' || $CI_COMMIT_BRANCH == 'develop'
changes:
paths:
- packages/backend-rs/**/*
@ -129,6 +176,7 @@ cargo_clippy:
- if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == 'main'
when: never
script:
- rustup component add clippy
- cargo clippy -- -D warnings
renovate:

View File

@ -1301,7 +1301,6 @@ export interface AbuseUserReportLike {
comment: string
}
export function publishToModerationStream(moderatorId: string, report: AbuseUserReportLike): void
export function publishToNotesStream(note: Note): void
export function getTimestamp(id: string): number
/**
* The generated ID results in the form of `[8 chars timestamp] + [cuid2]`.

View File

@ -310,7 +310,7 @@ if (!nativeBinding) {
throw new Error(`Failed to load native binding`)
}
const { SECOND, MINUTE, HOUR, DAY, USER_ONLINE_THRESHOLD, USER_ACTIVE_THRESHOLD, FILE_TYPE_BROWSERSAFE, loadEnv, loadConfig, stringToAcct, acctToString, addNoteToAntenna, isBlockedServer, isSilencedServer, isAllowedServer, checkWordMute, getFullApAccount, isSelfHost, isSameOrigin, extractHost, toPuny, isUnicodeEmoji, sqlLikeEscape, safeForSql, formatMilliseconds, getImageSizeFromUrl, getNoteSummary, isSafeUrl, latestVersion, toMastodonId, fromMastodonId, fetchMeta, metaToPugArgs, nyaify, hashPassword, verifyPassword, isOldPasswordAlgorithm, decodeReaction, countReactions, toDbReaction, removeOldAttestationChallenges, AntennaSrcEnum, DriveFileUsageHintEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, initializeRustLogger, fetchNodeinfo, nodeinfo_2_1, nodeinfo_2_0, Protocol, Inbound, Outbound, watchNote, unwatchNote, PushNotificationKind, sendPushNotification, publishToChannelStream, ChatEvent, publishToChatStream, ChatIndexEvent, publishToChatIndexStream, publishToBroadcastStream, publishToGroupChatStream, publishToModerationStream, publishToNotesStream, getTimestamp, genId, genIdAt, secureRndstr } = nativeBinding
const { SECOND, MINUTE, HOUR, DAY, USER_ONLINE_THRESHOLD, USER_ACTIVE_THRESHOLD, FILE_TYPE_BROWSERSAFE, loadEnv, loadConfig, stringToAcct, acctToString, addNoteToAntenna, isBlockedServer, isSilencedServer, isAllowedServer, checkWordMute, getFullApAccount, isSelfHost, isSameOrigin, extractHost, toPuny, isUnicodeEmoji, sqlLikeEscape, safeForSql, formatMilliseconds, getImageSizeFromUrl, getNoteSummary, isSafeUrl, latestVersion, toMastodonId, fromMastodonId, fetchMeta, metaToPugArgs, nyaify, hashPassword, verifyPassword, isOldPasswordAlgorithm, decodeReaction, countReactions, toDbReaction, removeOldAttestationChallenges, AntennaSrcEnum, DriveFileUsageHintEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, initializeRustLogger, fetchNodeinfo, nodeinfo_2_1, nodeinfo_2_0, Protocol, Inbound, Outbound, watchNote, unwatchNote, PushNotificationKind, sendPushNotification, publishToChannelStream, ChatEvent, publishToChatStream, ChatIndexEvent, publishToChatIndexStream, publishToBroadcastStream, publishToGroupChatStream, publishToModerationStream, getTimestamp, genId, genIdAt, secureRndstr } = nativeBinding
module.exports.SECOND = SECOND
module.exports.MINUTE = MINUTE
@ -383,7 +383,6 @@ module.exports.publishToChatIndexStream = publishToChatIndexStream
module.exports.publishToBroadcastStream = publishToBroadcastStream
module.exports.publishToGroupChatStream = publishToGroupChatStream
module.exports.publishToModerationStream = publishToModerationStream
module.exports.publishToNotesStream = publishToNotesStream
module.exports.getTimestamp = getTimestamp
module.exports.genId = genId
module.exports.genIdAt = genIdAt

View File

@ -5,7 +5,6 @@ pub mod chat_index;
pub mod custom_emoji;
pub mod group_chat;
pub mod moderation;
pub mod new_note;
use crate::config::CONFIG;
use crate::database::redis_conn;
@ -26,7 +25,7 @@ pub enum Stream {
#[strum(to_string = "noteStream:{note_id}")]
Note { note_id: String },
#[strum(serialize = "notesStream")]
NewNote,
Notes,
#[strum(to_string = "userListStream:{list_id}")]
UserList { list_id: String },
#[strum(to_string = "mainStream:{user_id}")]

View File

@ -1,10 +0,0 @@
use crate::model::entity::note;
use crate::service::stream::{publish_to_stream, Error, Stream};
// for napi export (https://github.com/napi-rs/napi-rs/issues/2060)
type Note = note::Model;
#[crate::export(js_name = "publishToNotesStream")]
pub fn publish(note: &Note) -> Result<(), Error> {
publish_to_stream(&Stream::NewNote, None, Some(serde_json::to_string(note)?))
}

View File

@ -1,5 +1,9 @@
import * as mfm from "mfm-js";
import { publishMainStream, publishNoteStream } from "@/services/stream.js";
import {
publishMainStream,
publishNotesStream,
publishNoteStream,
} from "@/services/stream.js";
import DeliverManager from "@/remote/activitypub/deliver-manager.js";
import renderNote from "@/remote/activitypub/renderer/note.js";
import renderCreate from "@/remote/activitypub/renderer/create.js";
@ -45,7 +49,6 @@ import {
genId,
genIdAt,
isSilencedServer,
publishToNotesStream,
} from "backend-rs";
import { countSameRenotes } from "@/misc/count-same-renotes.js";
import { deliverToRelays, getCachedRelays } from "../relay.js";
@ -508,7 +511,7 @@ export default async (
30,
);
}
publishToNotesStream(toRustObject(noteToPublish));
publishNotesStream(noteToPublish);
}
} finally {
await lock.release();

View File

@ -193,10 +193,9 @@ class Publisher {
// );
// };
/* ported to backend-rs */
// public publishNotesStream = (note: Note): void => {
// this.publish("notesStream", null, note);
// };
public publishNotesStream = (note: Note): void => {
this.publish("notesStream", null, note);
};
/* ported to backend-rs */
// public publishAdminStream = <K extends keyof AdminStreamTypes>(
@ -222,7 +221,7 @@ export const publishUserEvent = publisher.publishUserEvent;
export const publishMainStream = publisher.publishMainStream;
export const publishDriveStream = publisher.publishDriveStream;
export const publishNoteStream = publisher.publishNoteStream;
// export const publishNotesStream = publisher.publishNotesStream;
export const publishNotesStream = publisher.publishNotesStream;
// export const publishChannelStream = publisher.publishChannelStream;
export const publishUserListStream = publisher.publishUserListStream;
// export const publishAntennaStream = publisher.publishAntennaStream;

View File

@ -10,7 +10,7 @@
</template>
<script lang="ts" setup>
import { computed, onMounted, onUnmounted, ref } from "vue";
import { computed, onMounted, onUnmounted, ref, watch } from "vue";
import { i18n } from "@/i18n";
import { dateTimeFormat } from "@/scripts/intl-const";
@ -25,7 +25,7 @@ const props = withDefaults(
},
);
const _time =
const _time = computed(() =>
props.time == null
? Number.NaN
: typeof props.time === "number"
@ -33,16 +33,19 @@ const _time =
: (props.time instanceof Date
? props.time
: new Date(props.time)
).getTime();
const invalid = Number.isNaN(_time);
const absolute = !invalid ? dateTimeFormat.format(_time) : i18n.ts._ago.invalid;
).getTime(),
);
const invalid = computed(() => Number.isNaN(_time.value));
const absolute = computed(() =>
!invalid.value ? dateTimeFormat.format(_time.value) : i18n.ts._ago.invalid,
);
const now = ref(props.origin?.getTime() ?? Date.now());
const relative = computed<string>(() => {
if (props.mode === "absolute") return ""; // absoluterelative使
if (invalid) return i18n.ts._ago.invalid;
if (invalid.value) return i18n.ts._ago.invalid;
const ago = (now.value - _time) / 1000; /* ms */
const ago = (now.value - _time.value) / 1000; /* ms */
return ago >= 31536000
? i18n.t("_ago.yearsAgo", { n: Math.floor(ago / 31536000).toString() })
: ago >= 2592000
@ -74,15 +77,25 @@ const relative = computed<string>(() => {
: i18n.ts._ago.future;
});
let tickId: number;
let tickId: number | undefined;
function tick() {
if (
invalid.value ||
props.origin ||
(props.mode !== "relative" && props.mode !== "detail")
) {
if (tickId) window.clearInterval(tickId);
tickId = undefined;
return;
}
const _now = Date.now();
const agoPrev = (now.value - _time) / 1000; /* ms */ // interval
const agoPrev = (now.value - _time.value) / 1000; /* ms */ // interval
now.value = _now;
const ago = (now.value - _time) / 1000; /* ms */ // interval
const ago = (now.value - _time.value) / 1000; /* ms */ // interval
const prev = agoPrev < 60 ? 10000 : agoPrev < 3600 ? 60000 : 180000;
const next = ago < 60 ? 10000 : ago < 3600 ? 60000 : 180000;
@ -94,16 +107,13 @@ function tick() {
}
}
if (
!invalid &&
!props.origin &&
(props.mode === "relative" || props.mode === "detail")
) {
onMounted(() => {
tick();
});
onUnmounted(() => {
if (tickId) window.clearInterval(tickId);
});
}
watch(() => props.time, tick);
onMounted(() => {
tick();
});
onUnmounted(() => {
if (tickId) window.clearInterval(tickId);
});
</script>