mirror of
https://github.com/usememos/memos.git
synced 2025-03-20 12:40:09 +01:00
fix: wrong order of the timeline in the resource page & add webhook when create memos using Telegram bot (#2886)
* fix: wrong order in resource page timeline * feat: add webhook when create memos using Telegram bot * rename variables and fix typos for static checks
This commit is contained in:
parent
e78311b3af
commit
7cd3fcbc61
@ -6,6 +6,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"time"
|
||||||
"unicode/utf16"
|
"unicode/utf16"
|
||||||
|
|
||||||
"github.com/lithammer/shortuuid/v4"
|
"github.com/lithammer/shortuuid/v4"
|
||||||
@ -13,7 +14,9 @@ import (
|
|||||||
|
|
||||||
apiv1 "github.com/usememos/memos/api/v1"
|
apiv1 "github.com/usememos/memos/api/v1"
|
||||||
"github.com/usememos/memos/plugin/telegram"
|
"github.com/usememos/memos/plugin/telegram"
|
||||||
|
"github.com/usememos/memos/plugin/webhook"
|
||||||
storepb "github.com/usememos/memos/proto/gen/store"
|
storepb "github.com/usememos/memos/proto/gen/store"
|
||||||
|
"github.com/usememos/memos/server/service/metric"
|
||||||
"github.com/usememos/memos/store"
|
"github.com/usememos/memos/store"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -109,6 +112,9 @@ func (t *TelegramHandler) MessageHandle(ctx context.Context, bot *telegram.Bot,
|
|||||||
|
|
||||||
keyboard := generateKeyboardForMemoID(memoMessage.ID)
|
keyboard := generateKeyboardForMemoID(memoMessage.ID)
|
||||||
_, err = bot.EditMessage(ctx, message.Chat.ID, reply.MessageID, fmt.Sprintf("Saved as %s Memo %d", memoMessage.Visibility, memoMessage.ID), keyboard)
|
_, err = bot.EditMessage(ctx, message.Chat.ID, reply.MessageID, fmt.Sprintf("Saved as %s Memo %d", memoMessage.Visibility, memoMessage.ID), keyboard)
|
||||||
|
|
||||||
|
_ = t.dispatchMemoRelatedWebhook(ctx, *memoMessage, "memos.memo.created")
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,7 +141,15 @@ func (t *TelegramHandler) CallbackQueryHandle(ctx context.Context, bot *telegram
|
|||||||
return bot.AnswerCallbackQuery(ctx, callbackQuery.ID, fmt.Sprintf("Failed to EditMessage %s", err))
|
return bot.AnswerCallbackQuery(ctx, callbackQuery.ID, fmt.Sprintf("Failed to EditMessage %s", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
return bot.AnswerCallbackQuery(ctx, callbackQuery.ID, fmt.Sprintf("Success changing Memo %d to %s", memoID, visibility))
|
err = bot.AnswerCallbackQuery(ctx, callbackQuery.ID, fmt.Sprintf("Success changing Memo %d to %s", memoID, visibility))
|
||||||
|
|
||||||
|
memo, webhookErr := t.store.GetMemo(ctx, &store.FindMemo{
|
||||||
|
ID: &memoID,
|
||||||
|
})
|
||||||
|
if webhookErr == nil {
|
||||||
|
_ = t.dispatchMemoRelatedWebhook(ctx, *memo, "memos.memo.updated")
|
||||||
|
}
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateKeyboardForMemoID(id int32) [][]telegram.InlineKeyboardButton {
|
func generateKeyboardForMemoID(id int32) [][]telegram.InlineKeyboardButton {
|
||||||
@ -204,3 +218,79 @@ func convertToMarkdown(text string, messageEntities []telegram.MessageEntity) st
|
|||||||
|
|
||||||
return string(output)
|
return string(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *TelegramHandler) dispatchMemoRelatedWebhook(ctx context.Context, memo store.Memo, activityType string) error {
|
||||||
|
webhooks, err := t.store.ListWebhooks(ctx, &store.FindWebhook{
|
||||||
|
CreatorID: &memo.CreatorID,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
metric.Enqueue("webhook dispatch")
|
||||||
|
for _, hook := range webhooks {
|
||||||
|
payload := t.convertMemoToWebhookPayload(ctx, memo)
|
||||||
|
payload.ActivityType = activityType
|
||||||
|
payload.URL = hook.Url
|
||||||
|
err := webhook.Post(*payload)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "failed to post webhook")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TelegramHandler) convertMemoToWebhookPayload(ctx context.Context, memo store.Memo) (payload *webhook.WebhookPayload) {
|
||||||
|
payload = &webhook.WebhookPayload{
|
||||||
|
CreatorID: memo.CreatorID,
|
||||||
|
CreatedTs: time.Now().Unix(),
|
||||||
|
Memo: &webhook.Memo{
|
||||||
|
ID: memo.ID,
|
||||||
|
CreatorID: memo.CreatorID,
|
||||||
|
CreatedTs: memo.CreatedTs,
|
||||||
|
UpdatedTs: memo.UpdatedTs,
|
||||||
|
Content: memo.Content,
|
||||||
|
Visibility: memo.Visibility.String(),
|
||||||
|
Pinned: memo.Pinned,
|
||||||
|
ResourceList: make([]*webhook.Resource, 0),
|
||||||
|
RelationList: make([]*webhook.MemoRelation, 0),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
resourceList, err := t.store.ListResources(ctx, &store.FindResource{
|
||||||
|
MemoID: &memo.ID,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return payload
|
||||||
|
}
|
||||||
|
for _, resource := range resourceList {
|
||||||
|
payload.Memo.ResourceList = append(payload.Memo.ResourceList, &webhook.Resource{
|
||||||
|
ID: resource.ID,
|
||||||
|
CreatorID: resource.CreatorID,
|
||||||
|
CreatedTs: resource.CreatedTs,
|
||||||
|
UpdatedTs: resource.UpdatedTs,
|
||||||
|
Filename: resource.Filename,
|
||||||
|
Type: resource.Type,
|
||||||
|
Size: resource.Size,
|
||||||
|
InternalPath: resource.InternalPath,
|
||||||
|
ExternalLink: resource.ExternalLink,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
relationList, err := t.store.ListMemoRelations(ctx, &store.FindMemoRelation{
|
||||||
|
MemoID: &memo.ID,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return payload
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, relation := range relationList {
|
||||||
|
payload.Memo.RelationList = append(payload.Memo.RelationList, &webhook.MemoRelation{
|
||||||
|
MemoID: relation.MemoID,
|
||||||
|
RelatedMemoID: relation.RelatedMemoID,
|
||||||
|
Type: string(relation.Type),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return payload
|
||||||
|
}
|
||||||
|
@ -15,8 +15,15 @@ import { Resource } from "@/types/proto/api/v2/resource_service";
|
|||||||
import { useTranslate } from "@/utils/i18n";
|
import { useTranslate } from "@/utils/i18n";
|
||||||
|
|
||||||
function groupResourcesByDate(resources: Resource[]) {
|
function groupResourcesByDate(resources: Resource[]) {
|
||||||
|
const tmp_resources: Resource[] = resources.slice();
|
||||||
|
tmp_resources.sort((a: Resource, b: Resource) => {
|
||||||
|
const a_date = new Date(a.createTime as any);
|
||||||
|
const b_date = new Date(b.createTime as any);
|
||||||
|
return b_date.getTime() - a_date.getTime();
|
||||||
|
});
|
||||||
|
|
||||||
const grouped = new Map<number, Resource[]>();
|
const grouped = new Map<number, Resource[]>();
|
||||||
resources.forEach((item) => {
|
tmp_resources.forEach((item) => {
|
||||||
const date = new Date(item.createTime as any);
|
const date = new Date(item.createTime as any);
|
||||||
const year = date.getFullYear();
|
const year = date.getFullYear();
|
||||||
const month = date.getMonth() + 1;
|
const month = date.getMonth() + 1;
|
||||||
@ -41,15 +48,15 @@ const Resources = () => {
|
|||||||
});
|
});
|
||||||
const memoStore = useMemoStore();
|
const memoStore = useMemoStore();
|
||||||
const [resources, setResources] = useState<Resource[]>([]);
|
const [resources, setResources] = useState<Resource[]>([]);
|
||||||
const filteredResources = resources.filter((resource) => includes(resource.filename, state.searchQuery));
|
const filteredResources = resources.filter((resource: any) => includes(resource.filename, state.searchQuery));
|
||||||
const groupedResources = groupResourcesByDate(filteredResources.filter((resoure) => resoure.memoId));
|
const groupedResources = groupResourcesByDate(filteredResources.filter((resource: any) => resource.memoId));
|
||||||
const unusedResources = filteredResources.filter((resoure) => !resoure.memoId);
|
const unusedResources = filteredResources.filter((resource: any) => !resource.memoId);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
resourceServiceClient.listResources({}).then(({ resources }) => {
|
resourceServiceClient.listResources({}).then(({ resources }) => {
|
||||||
setResources(resources);
|
setResources(resources);
|
||||||
loadingState.setFinish();
|
loadingState.setFinish();
|
||||||
Promise.all(resources.map((resource) => (resource.memoId ? memoStore.getOrFetchMemoById(resource.memoId) : null)));
|
Promise.all(resources.map((resource: any) => (resource.memoId ? memoStore.getOrFetchMemoById(resource.memoId) : null)));
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@ -63,7 +70,7 @@ const Resources = () => {
|
|||||||
for (const resource of unusedResources) {
|
for (const resource of unusedResources) {
|
||||||
await resourceServiceClient.deleteResource({ id: resource.id });
|
await resourceServiceClient.deleteResource({ id: resource.id });
|
||||||
}
|
}
|
||||||
setResources(resources.filter((resoure) => resoure.memoId));
|
setResources(resources.filter((resource) => resource.memoId));
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user