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
pull/2931/head
Elliot Chen 1 year ago committed by GitHub
parent e78311b3af
commit 7cd3fcbc61
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -6,6 +6,7 @@ import (
"fmt"
"path/filepath"
"strconv"
"time"
"unicode/utf16"
"github.com/lithammer/shortuuid/v4"
@ -13,7 +14,9 @@ import (
apiv1 "github.com/usememos/memos/api/v1"
"github.com/usememos/memos/plugin/telegram"
"github.com/usememos/memos/plugin/webhook"
storepb "github.com/usememos/memos/proto/gen/store"
"github.com/usememos/memos/server/service/metric"
"github.com/usememos/memos/store"
)
@ -109,6 +112,9 @@ func (t *TelegramHandler) MessageHandle(ctx context.Context, bot *telegram.Bot,
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)
_ = t.dispatchMemoRelatedWebhook(ctx, *memoMessage, "memos.memo.created")
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("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 {
@ -204,3 +218,79 @@ func convertToMarkdown(text string, messageEntities []telegram.MessageEntity) st
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";
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[]>();
resources.forEach((item) => {
tmp_resources.forEach((item) => {
const date = new Date(item.createTime as any);
const year = date.getFullYear();
const month = date.getMonth() + 1;
@ -41,15 +48,15 @@ const Resources = () => {
});
const memoStore = useMemoStore();
const [resources, setResources] = useState<Resource[]>([]);
const filteredResources = resources.filter((resource) => includes(resource.filename, state.searchQuery));
const groupedResources = groupResourcesByDate(filteredResources.filter((resoure) => resoure.memoId));
const unusedResources = filteredResources.filter((resoure) => !resoure.memoId);
const filteredResources = resources.filter((resource: any) => includes(resource.filename, state.searchQuery));
const groupedResources = groupResourcesByDate(filteredResources.filter((resource: any) => resource.memoId));
const unusedResources = filteredResources.filter((resource: any) => !resource.memoId);
useEffect(() => {
resourceServiceClient.listResources({}).then(({ resources }) => {
setResources(resources);
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) {
await resourceServiceClient.deleteResource({ id: resource.id });
}
setResources(resources.filter((resoure) => resoure.memoId));
setResources(resources.filter((resource) => resource.memoId));
},
});
};

Loading…
Cancel
Save