Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: チャンネルミュートの実装 #14105

Open
wants to merge 24 commits into
base: develop
Choose a base branch
from

Conversation

samunohito
Copy link
Member

@samunohito samunohito commented Jun 30, 2024

※でかいので本線投入のタイミングは計りたい

fix: #10649

What

チャンネルミュートの機能を実装しました。

  • エンドポイントの追加
    • channels/mute/create
    • channels/mute/delete
    • channels/mute/list
  • 各TLのフィルタ時にチャンネルのミュート有無を考慮するように
    • HTL
      • ミュート中チャンネルのノートが流れてこなくなる
      • リノート含め/フォロー中のチャンネルも同様
    • LTL
      • ミュート中チャンネルのノートがチャンネル外にリノートされた場合でも流れてこなくなる
    • STL
      • LTL + HTL
    • リストTL
      • ミュート中チャンネルのノートがチャンネル外にリノートされた場合でも流れてこなくなる
    • ロールTL
      • ミュート中チャンネルのノートが流れてこなくなる
    • ユーザTL
      • そのユーザの投稿からミュート中チャンネルの投稿が省かれる
    • チャンネルTL
      • ミュート中でもそのチャンネル自体のTLは通常通り閲覧可能
      • ただし、ミュート中チャンネルの投稿を別チャンネルにリノートした場合はミュートされて見えなくなる

Why

fix: #10649

Additional info (optional)

  • unittestに新設したServiceのテストを追加
  • e2etestに各TL向けのテストを追加
  • pnpm migrate / revertによるエラーが無いことを確認

Checklist

  • Read the contribution guide
  • Test working in a local environment
  • (If needed) Add story of storybook
  • (If needed) Update CHANGELOG.md
  • (If possible) Add tests

@samunohito samunohito marked this pull request as draft June 30, 2024 13:22
@github-actions github-actions bot added packages/frontend Client side specific issue/PR packages/backend Server side specific issue/PR packages/misskey-js packages/backend:test labels Jun 30, 2024
@samunohito samunohito changed the title 【】feat: チャンネルミュートの実装 [wip] feat: チャンネルミュートの実装 Jun 30, 2024
Copy link
Contributor

github-actions bot commented Jun 30, 2024

このPRによるapi.jsonの差分

差分はこちら
--- base
+++ head
@@ -22427,6 +22427,494 @@
         }
       }
     },
+    "/channels/mute/create": {
+      "post": {
+        "operationId": "channels___mute___create",
+        "summary": "channels/mute/create",
+        "description": "No description provided.\n\n**Credential required**: *Yes* / **Permission**: *write:channels*",
+        "externalDocs": {
+          "description": "Source code",
+          "url": "https://github.com/misskey-dev/misskey/blob/develop/packages/backend/src/server/api/endpoints/channels/mute/create.ts"
+        },
+        "tags": [
+          "channels"
+        ],
+        "security": [
+          {
+            "bearerAuth": []
+          }
+        ],
+        "requestBody": {
+          "required": true,
+          "content": {
+            "application/json": {
+              "schema": {
+                "type": "object",
+                "properties": {
+                  "channelId": {
+                    "type": "string",
+                    "format": "misskey:id"
+                  },
+                  "expiresAt": {
+                    "type": [
+                      "integer",
+                      "null"
+                    ],
+                    "description": "A Unix Epoch timestamp that must lie in the future. `null` means an indefinite mute."
+                  }
+                },
+                "required": [
+                  "channelId"
+                ]
+              }
+            }
+          }
+        },
+        "responses": {
+          "204": {
+            "description": "OK (without any results)"
+          },
+          "400": {
+            "description": "Client error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Error"
+                },
+                "examples": {
+                  "NO_SUCH_CHANNEL": {
+                    "value": {
+                      "error": {
+                        "message": "No such Channel.",
+                        "code": "NO_SUCH_CHANNEL",
+                        "id": "7174361e-d58f-31d6-2e7c-6fb830786a3f"
+                      }
+                    }
+                  },
+                  "ALREADY_MUTING_CHANNEL": {
+                    "value": {
+                      "error": {
+                        "message": "You are already muting that user.",
+                        "code": "ALREADY_MUTING_CHANNEL",
+                        "id": "5a251978-769a-da44-3e89-3931e43bb592"
+                      }
+                    }
+                  },
+                  "EXPIRES_AT_IS_PAST": {
+                    "value": {
+                      "error": {
+                        "message": "Cannot set past date to \"expiresAt\".",
+                        "code": "EXPIRES_AT_IS_PAST",
+                        "id": "42b32236-df2c-a45f-fdbf-def67268f749"
+                      }
+                    }
+                  },
+                  "INVALID_PARAM": {
+                    "value": {
+                      "error": {
+                        "message": "Invalid param.",
+                        "code": "INVALID_PARAM",
+                        "id": "3d81ceae-475f-4600-b2a8-2bc116157532"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          },
+          "401": {
+            "description": "Authentication error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Error"
+                },
+                "examples": {
+                  "CREDENTIAL_REQUIRED": {
+                    "value": {
+                      "error": {
+                        "message": "Credential required.",
+                        "code": "CREDENTIAL_REQUIRED",
+                        "id": "1384574d-a912-4b81-8601-c7b1c4085df1"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          },
+          "403": {
+            "description": "Forbidden error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Error"
+                },
+                "examples": {
+                  "AUTHENTICATION_FAILED": {
+                    "value": {
+                      "error": {
+                        "message": "Authentication failed. Please ensure your token is correct.",
+                        "code": "AUTHENTICATION_FAILED",
+                        "id": "b0a7f5f8-dc2f-4171-b91f-de88ad238e14"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          },
+          "418": {
+            "description": "I'm Ai",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Error"
+                },
+                "examples": {
+                  "I_AM_AI": {
+                    "value": {
+                      "error": {
+                        "message": "You sent a request to Ai-chan, Misskey's showgirl, instead of the server.",
+                        "code": "I_AM_AI",
+                        "id": "60c46cd1-f23a-46b1-bebe-5d2b73951a84"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          },
+          "500": {
+            "description": "Internal server error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Error"
+                },
+                "examples": {
+                  "INTERNAL_ERROR": {
+                    "value": {
+                      "error": {
+                        "message": "Internal error occurred. Please contact us if the error persists.",
+                        "code": "INTERNAL_ERROR",
+                        "id": "5d37dbcb-891e-41ca-a3d6-e690c97775ac"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/channels/mute/delete": {
+      "post": {
+        "operationId": "channels___mute___delete",
+        "summary": "channels/mute/delete",
+        "description": "No description provided.\n\n**Credential required**: *Yes* / **Permission**: *write:channels*",
+        "externalDocs": {
+          "description": "Source code",
+          "url": "https://github.com/misskey-dev/misskey/blob/develop/packages/backend/src/server/api/endpoints/channels/mute/delete.ts"
+        },
+        "tags": [
+          "channels"
+        ],
+        "security": [
+          {
+            "bearerAuth": []
+          }
+        ],
+        "requestBody": {
+          "required": true,
+          "content": {
+            "application/json": {
+              "schema": {
+                "type": "object",
+                "properties": {
+                  "channelId": {
+                    "type": "string",
+                    "format": "misskey:id"
+                  }
+                },
+                "required": [
+                  "channelId"
+                ]
+              }
+            }
+          }
+        },
+        "responses": {
+          "204": {
+            "description": "OK (without any results)"
+          },
+          "400": {
+            "description": "Client error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Error"
+                },
+                "examples": {
+                  "NO_SUCH_CHANNEL": {
+                    "value": {
+                      "error": {
+                        "message": "No such Channel.",
+                        "code": "NO_SUCH_CHANNEL",
+                        "id": "e7998769-6e94-d9c2-6b8f-94a527314aba"
+                      }
+                    }
+                  },
+                  "NOT_MUTING_CHANNEL": {
+                    "value": {
+                      "error": {
+                        "message": "You are not muting that channel.",
+                        "code": "NOT_MUTING_CHANNEL",
+                        "id": "14d55962-6ea8-d990-1333-d6bef78dc2ab"
+                      }
+                    }
+                  },
+                  "INVALID_PARAM": {
+                    "value": {
+                      "error": {
+                        "message": "Invalid param.",
+                        "code": "INVALID_PARAM",
+                        "id": "3d81ceae-475f-4600-b2a8-2bc116157532"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          },
+          "401": {
+            "description": "Authentication error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Error"
+                },
+                "examples": {
+                  "CREDENTIAL_REQUIRED": {
+                    "value": {
+                      "error": {
+                        "message": "Credential required.",
+                        "code": "CREDENTIAL_REQUIRED",
+                        "id": "1384574d-a912-4b81-8601-c7b1c4085df1"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          },
+          "403": {
+            "description": "Forbidden error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Error"
+                },
+                "examples": {
+                  "AUTHENTICATION_FAILED": {
+                    "value": {
+                      "error": {
+                        "message": "Authentication failed. Please ensure your token is correct.",
+                        "code": "AUTHENTICATION_FAILED",
+                        "id": "b0a7f5f8-dc2f-4171-b91f-de88ad238e14"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          },
+          "418": {
+            "description": "I'm Ai",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Error"
+                },
+                "examples": {
+                  "I_AM_AI": {
+                    "value": {
+                      "error": {
+                        "message": "You sent a request to Ai-chan, Misskey's showgirl, instead of the server.",
+                        "code": "I_AM_AI",
+                        "id": "60c46cd1-f23a-46b1-bebe-5d2b73951a84"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          },
+          "500": {
+            "description": "Internal server error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Error"
+                },
+                "examples": {
+                  "INTERNAL_ERROR": {
+                    "value": {
+                      "error": {
+                        "message": "Internal error occurred. Please contact us if the error persists.",
+                        "code": "INTERNAL_ERROR",
+                        "id": "5d37dbcb-891e-41ca-a3d6-e690c97775ac"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/channels/mute/list": {
+      "post": {
+        "operationId": "channels___mute___list",
+        "summary": "channels/mute/list",
+        "description": "No description provided.\n\n**Credential required**: *Yes* / **Permission**: *read:channels*",
+        "externalDocs": {
+          "description": "Source code",
+          "url": "https://github.com/misskey-dev/misskey/blob/develop/packages/backend/src/server/api/endpoints/channels/mute/list.ts"
+        },
+        "tags": [
+          "channels"
+        ],
+        "security": [
+          {
+            "bearerAuth": []
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "OK (with results)",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "type": "object",
+                    "$ref": "#/components/schemas/Channel"
+                  }
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "Client error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Error"
+                },
+                "examples": {
+                  "INVALID_PARAM": {
+                    "value": {
+                      "error": {
+                        "message": "Invalid param.",
+                        "code": "INVALID_PARAM",
+                        "id": "3d81ceae-475f-4600-b2a8-2bc116157532"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          },
+          "401": {
+            "description": "Authentication error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Error"
+                },
+                "examples": {
+                  "CREDENTIAL_REQUIRED": {
+                    "value": {
+                      "error": {
+                        "message": "Credential required.",
+                        "code": "CREDENTIAL_REQUIRED",
+                        "id": "1384574d-a912-4b81-8601-c7b1c4085df1"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          },
+          "403": {
+            "description": "Forbidden error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Error"
+                },
+                "examples": {
+                  "AUTHENTICATION_FAILED": {
+                    "value": {
+                      "error": {
+                        "message": "Authentication failed. Please ensure your token is correct.",
+                        "code": "AUTHENTICATION_FAILED",
+                        "id": "b0a7f5f8-dc2f-4171-b91f-de88ad238e14"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          },
+          "418": {
+            "description": "I'm Ai",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Error"
+                },
+                "examples": {
+                  "I_AM_AI": {
+                    "value": {
+                      "error": {
+                        "message": "You sent a request to Ai-chan, Misskey's showgirl, instead of the server.",
+                        "code": "I_AM_AI",
+                        "id": "60c46cd1-f23a-46b1-bebe-5d2b73951a84"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          },
+          "500": {
+            "description": "Internal server error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Error"
+                },
+                "examples": {
+                  "INTERNAL_ERROR": {
+                    "value": {
+                      "error": {
+                        "message": "Internal error occurred. Please contact us if the error persists.",
+                        "code": "INTERNAL_ERROR",
+                        "id": "5d37dbcb-891e-41ca-a3d6-e690c97775ac"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    },
     "/charts/active-users": {
       "get": {
         "operationId": "charts___active-users",
@@ -79317,6 +79805,9 @@
           "isFavorited": {
             "type": "boolean"
           },
+          "isMuting": {
+            "type": "boolean"
+          },
           "pinnedNotes": {
             "type": "array",
             "items": {

Get diff files from Workflow Page

Copy link

codecov bot commented Jun 30, 2024

Codecov Report

Attention: Patch coverage is 53.75000% with 518 lines in your changes missing coverage. Please review.

Project coverage is 41.59%. Comparing base (984d582) to head (0f574b7).

Files Patch % Lines
.../backend/src/core/entities/ChannelEntityService.ts 10.52% 119 Missing ⚠️
packages/frontend/src/pages/channel.vue 0.00% 75 Missing ⚠️
...d/src/server/api/endpoints/channels/mute/create.ts 62.22% 34 Missing ⚠️
...backend/src/server/api/endpoints/notes/timeline.ts 9.09% 30 Missing ⚠️
.../backend/src/server/api/stream/channels/channel.ts 9.37% 29 Missing ⚠️
...d/src/server/api/endpoints/channels/mute/delete.ts 61.64% 28 Missing ⚠️
...es/backend/src/server/api/endpoints/users/notes.ts 3.70% 26 Missing ⚠️
.../src/server/api/stream/channels/hybrid-timeline.ts 4.16% 23 Missing ⚠️
.../src/server/api/endpoints/notes/hybrid-timeline.ts 18.18% 18 Missing ⚠️
...kend/src/server/api/endpoints/channels/timeline.ts 10.52% 17 Missing ⚠️
... and 12 more
Additional details and impacted files
@@             Coverage Diff             @@
##           develop   #14105      +/-   ##
===========================================
+ Coverage    40.15%   41.59%   +1.44%     
===========================================
  Files         1517     1526       +9     
  Lines       187327   193010    +5683     
  Branches      3470     3555      +85     
===========================================
+ Hits         75213    80284    +5071     
- Misses      111546   112156     +610     
- Partials       568      570       +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@samunohito
Copy link
Member Author

image
チャンネルのミュート・アンミュートはこちらから。
分かりにくい位置になってしまいましたが、今の画面構成だとここに置くのが限界だと思い…

ユーザのフォロー画面のように出来ればいいのかもしれませんが、あまり派手に変えるとチャンネルミュートの本筋から逸れてしまうのでひとまずこの形式で実装しました。

@samunohito samunohito changed the title [wip] feat: チャンネルミュートの実装 feat: チャンネルミュートの実装 Jul 7, 2024
@samunohito samunohito marked this pull request as ready for review July 7, 2024 02:38
@samunohito
Copy link
Member Author

ready for review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
packages/backend:test packages/backend Server side specific issue/PR packages/frontend Client side specific issue/PR packages/misskey-js
Projects
None yet
Development

Successfully merging this pull request may close these issues.

チャンネルをミュート
1 participant