mirror of https://github.com/usbharu/Hideout.git
feat: Mastodonの通知APIのNotificationStoreを追加
This commit is contained in:
parent
cf5c396d32
commit
ee3681468b
|
@ -0,0 +1,17 @@
|
|||
package dev.usbharu.hideout.mastodon.domain.model
|
||||
|
||||
import org.springframework.data.annotation.Id
|
||||
import org.springframework.data.mongodb.core.mapping.Document
|
||||
import java.time.Instant
|
||||
|
||||
@Document
|
||||
data class MastodonNotification(
|
||||
@Id
|
||||
val id: Long,
|
||||
val type: NotificationType,
|
||||
val createdAt: Instant,
|
||||
val accountId: Long,
|
||||
val statusId: Long?,
|
||||
val reportId: Long?,
|
||||
val relationshipServeranceEvent: Long?
|
||||
)
|
|
@ -0,0 +1,7 @@
|
|||
package dev.usbharu.hideout.mastodon.domain.model
|
||||
|
||||
interface MastodonNotificationRepository {
|
||||
suspend fun save(mastodonNotification: MastodonNotification): MastodonNotification
|
||||
suspend fun deleteById(id: Long)
|
||||
suspend fun findById(id: Long): MastodonNotification?
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package dev.usbharu.hideout.mastodon.domain.model
|
||||
|
||||
enum class NotificationType {
|
||||
mention,
|
||||
status,
|
||||
reblog,
|
||||
follow,
|
||||
follow_request,
|
||||
favourite,
|
||||
poll,
|
||||
update,
|
||||
admin_sign_up,
|
||||
admin_report,
|
||||
severed_relationships;
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
package dev.usbharu.hideout.mastodon.infrastructure.exposedrepository
|
||||
|
||||
import dev.usbharu.hideout.core.infrastructure.exposedrepository.AbstractRepository
|
||||
import dev.usbharu.hideout.mastodon.domain.model.MastodonNotification
|
||||
import dev.usbharu.hideout.mastodon.domain.model.MastodonNotificationRepository
|
||||
import dev.usbharu.hideout.mastodon.domain.model.NotificationType
|
||||
import org.jetbrains.exposed.sql.*
|
||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
|
||||
import org.jetbrains.exposed.sql.javatime.timestamp
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.beans.factory.annotation.Qualifier
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
|
||||
import org.springframework.stereotype.Repository
|
||||
|
||||
@Repository
|
||||
@Qualifier("jdbc")
|
||||
@ConditionalOnProperty("hideout.use-mongodb", havingValue = "false", matchIfMissing = true)
|
||||
class ExposedMastodonNotificationRepository : MastodonNotificationRepository, AbstractRepository() {
|
||||
override val logger: Logger
|
||||
get() = Companion.logger
|
||||
|
||||
override suspend fun save(mastodonNotification: MastodonNotification): MastodonNotification = query {
|
||||
val singleOrNull =
|
||||
MastodonNotifications.select { MastodonNotifications.id eq mastodonNotification.id }.singleOrNull()
|
||||
if (singleOrNull == null) {
|
||||
MastodonNotifications.insert {
|
||||
it[MastodonNotifications.id] = mastodonNotification.id
|
||||
it[MastodonNotifications.type] = mastodonNotification.type.name
|
||||
it[MastodonNotifications.createdAt] = mastodonNotification.createdAt
|
||||
it[MastodonNotifications.accountId] = mastodonNotification.accountId
|
||||
it[MastodonNotifications.statusId] = mastodonNotification.statusId
|
||||
it[MastodonNotifications.reportId] = mastodonNotification.reportId
|
||||
it[MastodonNotifications.relationshipServeranceEventId] =
|
||||
mastodonNotification.relationshipServeranceEvent
|
||||
}
|
||||
} else {
|
||||
MastodonNotifications.update({ MastodonNotifications.id eq mastodonNotification.id }) {
|
||||
it[MastodonNotifications.type] = mastodonNotification.type.name
|
||||
it[MastodonNotifications.createdAt] = mastodonNotification.createdAt
|
||||
it[MastodonNotifications.accountId] = mastodonNotification.accountId
|
||||
it[MastodonNotifications.statusId] = mastodonNotification.statusId
|
||||
it[MastodonNotifications.reportId] = mastodonNotification.reportId
|
||||
it[MastodonNotifications.relationshipServeranceEventId] =
|
||||
mastodonNotification.relationshipServeranceEvent
|
||||
}
|
||||
}
|
||||
mastodonNotification
|
||||
}
|
||||
|
||||
override suspend fun deleteById(id: Long): Unit = query {
|
||||
MastodonNotifications.deleteWhere {
|
||||
MastodonNotifications.id eq id
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun findById(id: Long): MastodonNotification? = query {
|
||||
MastodonNotifications.select { MastodonNotifications.id eq id }.singleOrNull()?.toMastodonNotification()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val logger = LoggerFactory.getLogger(ExposedMastodonNotificationRepository::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
fun ResultRow.toMastodonNotification(): MastodonNotification {
|
||||
return MastodonNotification(
|
||||
this[MastodonNotifications.id],
|
||||
NotificationType.valueOf(this[MastodonNotifications.type]),
|
||||
this[MastodonNotifications.createdAt],
|
||||
this[MastodonNotifications.accountId],
|
||||
this[MastodonNotifications.statusId],
|
||||
this[MastodonNotifications.reportId],
|
||||
this[MastodonNotifications.relationshipServeranceEventId],
|
||||
)
|
||||
}
|
||||
|
||||
object MastodonNotifications : Table("mastodon_notifications") {
|
||||
val id = long("id")
|
||||
val type = varchar("type", 100)
|
||||
val createdAt = timestamp("created_at")
|
||||
val accountId = long("account_id")
|
||||
val statusId = long("status_id").nullable()
|
||||
val reportId = long("report_id").nullable()
|
||||
val relationshipServeranceEventId = long("relationship_serverance_event_id").nullable()
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package dev.usbharu.hideout.mastodon.infrastructure.mongorepository
|
||||
|
||||
import dev.usbharu.hideout.mastodon.domain.model.MastodonNotification
|
||||
import org.springframework.data.mongodb.repository.MongoRepository
|
||||
|
||||
interface MongoMastodonNotificationRepository : MongoRepository<MastodonNotification, Long> {
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package dev.usbharu.hideout.mastodon.infrastructure.mongorepository
|
||||
|
||||
import dev.usbharu.hideout.mastodon.domain.model.MastodonNotification
|
||||
import dev.usbharu.hideout.mastodon.domain.model.MastodonNotificationRepository
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
|
||||
import org.springframework.stereotype.Repository
|
||||
import kotlin.jvm.optionals.getOrNull
|
||||
|
||||
@Repository
|
||||
@ConditionalOnProperty("hideout.use-mongodb", havingValue = "true", matchIfMissing = false)
|
||||
class MongoMastodonNotificationRepositoryWrapper(private val mongoMastodonNotificationRepository: MongoMastodonNotificationRepository) :
|
||||
MastodonNotificationRepository {
|
||||
override suspend fun save(mastodonNotification: MastodonNotification): MastodonNotification {
|
||||
return mongoMastodonNotificationRepository.save(mastodonNotification)
|
||||
}
|
||||
|
||||
override suspend fun deleteById(id: Long) {
|
||||
mongoMastodonNotificationRepository.deleteById(id)
|
||||
}
|
||||
|
||||
override suspend fun findById(id: Long): MastodonNotification? {
|
||||
return mongoMastodonNotificationRepository.findById(id).getOrNull()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
package dev.usbharu.hideout.mastodon.service.notification
|
||||
|
||||
import dev.usbharu.hideout.core.domain.model.actor.Actor
|
||||
import dev.usbharu.hideout.core.domain.model.notification.Notification
|
||||
import dev.usbharu.hideout.core.domain.model.post.Post
|
||||
import dev.usbharu.hideout.core.domain.model.reaction.Reaction
|
||||
import dev.usbharu.hideout.core.service.notification.NotificationStore
|
||||
import dev.usbharu.hideout.mastodon.domain.model.MastodonNotification
|
||||
import dev.usbharu.hideout.mastodon.domain.model.MastodonNotificationRepository
|
||||
import dev.usbharu.hideout.mastodon.domain.model.NotificationType
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
@Component
|
||||
class MastodonNotificationStore(private val mastodonNotificationRepository: MastodonNotificationRepository) :
|
||||
NotificationStore {
|
||||
override suspend fun publishNotification(
|
||||
notification: Notification,
|
||||
user: Actor,
|
||||
sourceActor: Actor?,
|
||||
post: Post?,
|
||||
reaction: Reaction?
|
||||
): Boolean {
|
||||
val notificationType = when (notification.type) {
|
||||
"mention" -> NotificationType.mention
|
||||
"post" -> NotificationType.status
|
||||
"repost" -> NotificationType.reblog
|
||||
"follow" -> NotificationType.follow
|
||||
"follow-request" -> NotificationType.follow_request
|
||||
"reaction" -> NotificationType.favourite
|
||||
else -> {
|
||||
logger.debug("Notification type does not support. type: {}", notification.type)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if (notification.sourceActorId == null) {
|
||||
logger.debug("Notification does not support. notification.sourceActorId is null")
|
||||
return false
|
||||
}
|
||||
|
||||
val mastodonNotification = MastodonNotification(
|
||||
id = notification.id,
|
||||
type = notificationType,
|
||||
createdAt = notification.createdAt,
|
||||
accountId = notification.sourceActorId,
|
||||
statusId = notification.postId,
|
||||
reportId = null,
|
||||
relationshipServeranceEvent = null
|
||||
)
|
||||
|
||||
mastodonNotificationRepository.save(mastodonNotification)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override suspend fun unpulishNotification(notificationId: Long): Boolean {
|
||||
mastodonNotificationRepository.deleteById(notificationId)
|
||||
return true
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val logger = LoggerFactory.getLogger(MastodonNotificationStore::class.java)
|
||||
}
|
||||
}
|
|
@ -19,6 +19,8 @@ tags:
|
|||
description: timeline
|
||||
- name: media
|
||||
description: media
|
||||
- name: notification
|
||||
description: notification
|
||||
|
||||
paths:
|
||||
/api/v2/instance:
|
||||
|
@ -803,6 +805,122 @@ paths:
|
|||
schema:
|
||||
$ref: "#/components/schemas/Relationship"
|
||||
|
||||
/api/v1/notifications:
|
||||
get:
|
||||
tags:
|
||||
- notifications
|
||||
security:
|
||||
- OAuth2:
|
||||
- "read:notifications"
|
||||
parameters:
|
||||
- in: query
|
||||
name: max_id
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: since_id
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: min_id
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: limit
|
||||
required: false
|
||||
schema:
|
||||
type: integer
|
||||
- in: query
|
||||
name: types[]
|
||||
required: false
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
- in: query
|
||||
name: exclude_types[]
|
||||
required: false
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
- in: query
|
||||
name: account_id
|
||||
required: false
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
responses:
|
||||
200:
|
||||
description: 成功
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/Notification"
|
||||
|
||||
/api/v1/notifications/{id}:
|
||||
get:
|
||||
tags:
|
||||
- notifications
|
||||
security:
|
||||
- OAuth2:
|
||||
- "read:notifications"
|
||||
parameters:
|
||||
- in: path
|
||||
required: true
|
||||
name: id
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
200:
|
||||
description: 成功
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Notification"
|
||||
|
||||
/api/v1/notifications/clear:
|
||||
post:
|
||||
tags:
|
||||
- notifications
|
||||
security:
|
||||
- OAuth2:
|
||||
- "write:notifications"
|
||||
responses:
|
||||
200:
|
||||
description: 成功
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
|
||||
/api/v1/notifications/{id}/dismiss:
|
||||
post:
|
||||
tags:
|
||||
- notifications
|
||||
security:
|
||||
- OAuth2:
|
||||
- "write:notifications"
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
200:
|
||||
description: 成功
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
|
||||
components:
|
||||
schemas:
|
||||
V1MediaRequest:
|
||||
|
@ -1935,6 +2053,47 @@ components:
|
|||
value:
|
||||
type: string
|
||||
|
||||
Report:
|
||||
type: object
|
||||
|
||||
RelationshipServeranceEvent:
|
||||
type: object
|
||||
|
||||
Notification:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- mention
|
||||
- status
|
||||
- reblog
|
||||
- follow
|
||||
- follow_request
|
||||
- favourite
|
||||
- poll
|
||||
- update
|
||||
- admin.sign_up
|
||||
- admin.report
|
||||
- severed_relationships
|
||||
created_at:
|
||||
type: string
|
||||
account:
|
||||
$ref: "#/components/schemas/Account"
|
||||
status:
|
||||
$ref: "#/components/schemas/Status"
|
||||
report:
|
||||
$ref: "#/components/schemas/Report"
|
||||
relationship_severance_event:
|
||||
$ref: "#/components/schemas/RelationshipServeranceEvent"
|
||||
required:
|
||||
- id
|
||||
- type
|
||||
- created_at
|
||||
- account
|
||||
|
||||
securitySchemes:
|
||||
OAuth2:
|
||||
type: oauth2
|
||||
|
|
Loading…
Reference in New Issue