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: 予約投稿 #12265

Closed
wants to merge 65 commits into from
Closed

Conversation

mattyatea
Copy link
Member

@mattyatea mattyatea commented Nov 6, 2023

What

予約投稿が追加されます。
作業中です。

Why

予約投稿がないと不便だという意見もみられるため?

Additional info (optional)

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

Signed-off-by: mattyatea <mattyacocacora0@gmail.com>
@github-actions github-actions bot added packages/frontend Client side specific issue/PR packages/backend Server side specific issue/PR labels Nov 6, 2023
Copy link

codecov bot commented Nov 6, 2023

Codecov Report

Attention: 172 lines in your changes are missing coverage. Please review.

Comparison is base (5299d17) 64.35% compared to head (dfc5be6) 65.89%.

Files Patch % Lines
...s/backend/src/server/api/endpoints/notes/create.ts 46.93% 52 Missing ⚠️
...nd/src/server/api/endpoints/notes/schedule/list.ts 57.33% 32 Missing ⚠️
...eue/processors/ScheduleNotePostProcessorService.ts 61.40% 22 Missing ⚠️
packages/backend/src/core/NoteScheduleService.ts 60.46% 17 Missing ⚠️
packages/backend/src/queue/types.ts 0.00% 16 Missing ⚠️
.../src/server/api/endpoints/notes/schedule/delete.ts 74.07% 14 Missing ⚠️
packages/frontend/src/os.ts 0.00% 7 Missing ⚠️
packages/backend/src/models/Notification.ts 0.00% 5 Missing ⚠️
packages/backend/src/server/api/endpoints/i.ts 50.00% 3 Missing ⚠️
...ages/backend/src/server/web/ClientServerService.ts 83.33% 2 Missing ⚠️
... and 2 more
Additional details and impacted files
@@             Coverage Diff             @@
##           develop   #12265      +/-   ##
===========================================
+ Coverage    64.35%   65.89%   +1.53%     
===========================================
  Files          979      989      +10     
  Lines       109398   114781    +5383     
  Branches      4290     5694    +1404     
===========================================
+ Hits         70408    75630    +5222     
- Misses       38958    39117     +159     
- Partials        32       34       +2     

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

@mattyatea
Copy link
Member Author

redisに保存するようになってるからredis飛んだときとかがあれかもしれない
けどdbに保存するとなると毎分dbにアクセスしなくちゃいけないから...って思ってます

@kakkokari-gtyih kakkokari-gtyih linked an issue Nov 6, 2023 that may be closed by this pull request
@kakkokari-gtyih
Copy link
Contributor

kakkokari-gtyih commented Nov 6, 2023

redisに保存するようになってるからredis飛んだときとかがあれかもしれない

  • 予約投稿専用IDを発番する
  • そのIDと投稿予定時刻をRedisに突っ込む
  • 投稿+予約投稿専用IDをDBに突っ込む
  • 予約投稿発火時にRedis・DBから当該項目を削除

で解決できそう(ついでに予約一覧の表示もやりやすくなるかも?)

Signed-off-by: mattyatea <mattyacocacora0@gmail.com>
Copy link
Contributor

github-actions bot commented Nov 8, 2023

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

差分はこちら
--- base
+++ head
@@ -42983,6 +42983,7 @@
                         "followRequestAccepted",
                         "roleAssigned",
                         "achievementEarned",
+                        "noteSchedulingFailed",
                         "app",
                         "test",
                         "pollVote",
@@ -43007,6 +43008,7 @@
                         "followRequestAccepted",
                         "roleAssigned",
                         "achievementEarned",
+                        "noteSchedulingFailed",
                         "app",
                         "test",
                         "pollVote",
@@ -43222,6 +43224,7 @@
                         "followRequestAccepted",
                         "roleAssigned",
                         "achievementEarned",
+                        "noteSchedulingFailed",
                         "app",
                         "test",
                         "pollVote",
@@ -43246,6 +43249,7 @@
                         "followRequestAccepted",
                         "roleAssigned",
                         "achievementEarned",
+                        "noteSchedulingFailed",
                         "app",
                         "test",
                         "pollVote",
@@ -52343,6 +52347,17 @@
                     "required": [
                       "choices"
                     ]
+                  },
+                  "schedule": {
+                    "type": [
+                      "object",
+                      "null"
+                    ],
+                    "properties": {
+                      "scheduledAt": {
+                        "type": "string"
+                      }
+                    }
                   }
                 },
                 "if": {
@@ -52358,6 +52373,9 @@
                     },
                     "poll": {
                       "type": "null"
+                    },
+                    "schedule": {
+                      "type": "null"
                     }
                   }
                 },
@@ -52387,8 +52405,27 @@
                   "type": "object",
                   "properties": {
                     "createdNote": {
-                      "type": "object",
-                      "$ref": "#/components/schemas/Note"
+                      "type": [
+                        "object",
+                        "null"
+                      ],
+                      "allOf": [
+                        {
+                          "$ref": "#/components/schemas/Note"
+                        }
+                      ]
+                    },
+                    "scheduledNoteId": {
+                      "type": [
+                        "string",
+                        "null"
+                      ]
+                    },
+                    "scheduledNote": {
+                      "type": [
+                        "object",
+                        "null"
+                      ]
                     }
                   },
                   "required": [
@@ -52505,6 +52542,221 @@
                       }
                     }
                   },
+                  "CANNOT_CREATE_ALREADY_EXPIRED_SCHEDULE": {
+                    "value": {
+                      "error": {
+                        "message": "Schedule is already expired.",
+                        "code": "CANNOT_CREATE_ALREADY_EXPIRED_SCHEDULE",
+                        "id": "8a9bfb90-fc7e-4878-a3e8-d97faaf5fb07"
+                      }
+                    }
+                  },
+                  "PLEASE_SPECIFY_SCHEDULE_DATE": {
+                    "value": {
+                      "error": {
+                        "message": "Please specify schedule date.",
+                        "code": "PLEASE_SPECIFY_SCHEDULE_DATE",
+                        "id": "c93a6ad6-f7e2-4156-a0c2-3d03529e5e0f"
+                      }
+                    }
+                  },
+                  "NO_SUCH_SCHEDULE": {
+                    "value": {
+                      "error": {
+                        "message": "No such schedule.",
+                        "code": "NO_SUCH_SCHEDULE",
+                        "id": "44dee229-8da1-4a61-856d-e3a4bbc12032"
+                      }
+                    }
+                  },
+                  "ROLE_PERMISSION_DENIED": {
+                    "value": {
+                      "error": {
+                        "message": "You are not assigned to a required role.",
+                        "code": "ROLE_PERMISSION_DENIED",
+                        "kind": "permission",
+                        "id": "7f86f06f-7e15-4057-8561-f4b6d4ac755a"
+                      }
+                    }
+                  },
+                  "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"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          },
+          "429": {
+            "description": "To many requests",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Error"
+                },
+                "examples": {
+                  "RATE_LIMIT_EXCEEDED": {
+                    "value": {
+                      "error": {
+                        "message": "Rate limit exceeded. Please try again later.",
+                        "code": "RATE_LIMIT_EXCEEDED",
+                        "id": "d5826d14-3982-4d2e-8011-b9e9f02499ef"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          },
+          "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"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/notes/schedule/delete": {
+      "post": {
+        "operationId": "notes/schedule/delete",
+        "summary": "notes/schedule/delete",
+        "description": "No description provided.\n\n**Credential required**: *Yes* / **Permission**: *write:notes*",
+        "externalDocs": {
+          "description": "Source code",
+          "url": "https://github.com/misskey-dev/misskey/blob/develop/packages/backend/src/server/api/endpoints/notes/schedule/delete.ts"
+        },
+        "tags": [
+          "notes"
+        ],
+        "security": [
+          {
+            "bearerAuth": []
+          }
+        ],
+        "requestBody": {
+          "required": true,
+          "content": {
+            "application/json": {
+              "schema": {
+                "type": "object",
+                "properties": {
+                  "scheduledNoteId": {
+                    "type": "string",
+                    "format": "misskey:id"
+                  }
+                },
+                "required": [
+                  "scheduledNoteId"
+                ]
+              }
+            }
+          }
+        },
+        "responses": {
+          "204": {
+            "description": "OK (without any results)"
+          },
+          "400": {
+            "description": "Client error",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/Error"
+                },
+                "examples": {
+                  "NO_SUCH_NOTE": {
+                    "value": {
+                      "error": {
+                        "message": "No such note.",
+                        "code": "NO_SUCH_NOTE",
+                        "id": "490be23f-8c1f-4796-819f-94cb4f9d1630"
+                      }
+                    }
+                  },
                   "INVALID_PARAM": {
                     "value": {
                       "error": {
@@ -52626,6 +52878,171 @@
         }
       }
     },
+    "/notes/schedule/list": {
+      "post": {
+        "operationId": "notes/schedule/list",
+        "summary": "notes/schedule/list",
+        "description": "No description provided.\n\n**Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties.\n**Credential required**: *Yes* / **Permission**: *read:notes*",
+        "externalDocs": {
+          "description": "Source code",
+          "url": "https://github.com/misskey-dev/misskey/blob/develop/packages/backend/src/server/api/endpoints/notes/schedule/list.ts"
+        },
+        "tags": [
+          "notes"
+        ],
+        "security": [
+          {
+            "bearerAuth": []
+          }
+        ],
+        "requestBody": {
+          "required": true,
+          "content": {
+            "application/json": {
+              "schema": {
+                "type": "object",
+                "properties": {
+                  "sinceId": {
+                    "type": "string",
+                    "format": "misskey:id"
+                  },
+                  "untilId": {
+                    "type": "string",
+                    "format": "misskey:id"
+                  },
+                  "limit": {
+                    "type": "integer",
+                    "minimum": 1,
+                    "maximum": 100,
+                    "default": 10
+                  }
+                }
+              }
+            }
+          }
+        },
+        "responses": {
+          "200": {
+            "description": "OK (with results)",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "type": "object"
+                  }
+                }
+              }
+            }
+          },
+          "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"
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    },
     "/notes/delete": {
       "post": {
         "operationId": "notes/delete",
@@ -76106,6 +76523,9 @@
           "canPublicNote": {
             "type": "boolean"
           },
+          "canScheduleNote": {
+            "type": "boolean"
+          },
           "canInvite": {
             "type": "boolean"
           },
@@ -76174,6 +76594,7 @@
           "gtlAvailable",
           "ltlAvailable",
           "canPublicNote",
+          "canScheduleNote",
           "canInvite",
           "inviteLimit",
           "inviteLimitCycle",

Get diff files from Workflow Page

.
Signed-off-by: mattyatea <mattyacocacora0@gmail.com>
dbに投稿内容を保存するようにした

Signed-off-by: mattyatea <mattyacocacora0@gmail.com>
Signed-off-by: mattyatea <mattyacocacora0@gmail.com>
@kakkokari-gtyih
Copy link
Contributor

kakkokari-gtyih commented Nov 9, 2023

UI周りちょっと見てみてもいいですか?

@kakkokari-gtyih
Copy link
Contributor

やろうとしてること

  • 予約投稿関連のエンドポイントを全部/api/notes/schedule/配下に置き直す
  • 予約投稿単体でダイアログ出せるように
  • 投稿編集時はPostFormの表記を変更するように
  • その他フロントエンドの細かい調整

Signed-off-by: mattyatea <mattyacocacora0@gmail.com>
@mattyatea
Copy link
Member Author

そこ周り少し変更加えたので一回pushします

@kakkokari-gtyih
Copy link
Contributor

予約投稿関連のエンドポイントを全部/api/notes/schedule/配下に置き直す

(やったけど変なところにpushしてしまったので少々お待ちください)

@kakkokari-gtyih
Copy link
Contributor

  • 予約投稿一覧にMkPaginationをつける(一応)
    • (API側でPaginationQueryを使う)
  • 予約投稿の時刻設定をUNIXタイムスタンプではなくISO8601で指定できるようにする

くらいかなと

syuilo
syuilo previously requested changes Nov 9, 2023
Copy link
Member

@syuilo syuilo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NoteSchedule --> ScheduledNote
(一括置換)

@syuilo
Copy link
Member

syuilo commented Nov 9, 2023

NoteSchedule --> ScheduledNote (一括置換)

あーノートというよりスケジュール自体だからいいのか?

Signed-off-by: mattyatea <mattyacocacora0@gmail.com>
Signed-off-by: mattyatea <mattyacocacora0@gmail.com>
Signed-off-by: mattyatea <mattyacocacora0@gmail.com>
Signed-off-by: mattyatea <mattyacocacora0@gmail.com>
Signed-off-by: mattyatea <mattyacocacora0@gmail.com>
@kakkokari-gtyih
Copy link
Contributor

pnpm build-misskey-js-with-types

Signed-off-by: mattyatea <mattyacocacora0@gmail.com>
@mattyatea
Copy link
Member Author

ありがとうございます🙏

@kakkokari-gtyih
Copy link
Contributor

Github Workflowのマージに失敗してる(バージョンが戻されてる)ので元に戻す

いけた(ので動作確認だけしたらreadyにできそう)

@kakkokari-gtyih
Copy link
Contributor

submoduleのdiffだけ取っ払いたい

import { id } from './util/id.js';
import { MiUser } from './User.js';

@Entity('note_schedule')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

クラス名と一致してないわね

@mattyatea mattyatea closed this Jun 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
packages/backend Server side specific issue/PR packages/frontend Client side specific issue/PR packages/misskey-js packages/sw
Projects
None yet
Development

Successfully merging this pull request may close these issues.

予約投稿
3 participants