-
Notifications
You must be signed in to change notification settings - Fork 0
/
webhookService.js
137 lines (117 loc) · 4.51 KB
/
webhookService.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
const YAML = require('yaml');
class WebhookService {
static validateUrl(url) {
try {
new URL(url);
return true;
} catch {
return false;
}
}
static parseYamlFrontmatter(content) {
const yamlRegex = /^---\n([\s\S]*?)\n---/;
const match = content.match(yamlRegex);
if (match) {
try {
const yamlContent = match[1];
const parsedYaml = YAML.parse(yamlContent);
const remainingContent = content.slice(match[0].length).trim();
return {
frontmatter: parsedYaml,
content: remainingContent
};
} catch (error) {
console.error('YAML parsing error:', error);
return {
frontmatter: {},
content: content
};
}
}
return {
frontmatter: {},
content: content
};
}
static async getAttachments(app, content, notePath) {
const attachments = [];
const attachmentRegex = /!?\[\[([^\]]+?)(?:\|[^\]]+)?\]\]|!\[(.*?)\]\(([^)]+)\)/g;
const matches = [...content.matchAll(attachmentRegex)];
for (const match of matches) {
try {
// Get attachment name from either wiki-link or markdown format
let attachmentName = match[1] || match[3] || '';
attachmentName = attachmentName.split('|')[0].trim();
if (!attachmentName) continue;
// Handle both absolute and relative paths
let file = null;
// Try getting the file directly first
file = app.vault.getAbstractFileByPath(attachmentName);
// If not found, try resolving relative to the note
if (!file) {
file = app.metadataCache.getFirstLinkpathDest(attachmentName, notePath);
}
// If still not found, check in attachments folder
if (!file) {
const attachmentFolder = app.vault.config.attachmentFolderPath || '';
if (attachmentFolder) {
const fullPath = `${attachmentFolder}/${attachmentName}`;
file = app.vault.getAbstractFileByPath(fullPath);
}
}
if (file && !file.children) { // Check that it's not a folder
const arrayBuffer = await app.vault.readBinary(file);
const base64 = this.arrayBufferToBase64(arrayBuffer);
attachments.push({
name: file.name,
type: file.extension,
size: arrayBuffer.byteLength,
data: base64,
path: file.path
});
}
} catch (error) {
console.error(`Failed to process attachment: ${error.message}`);
}
}
return attachments;
}
static arrayBufferToBase64(buffer) {
let binary = '';
const bytes = new Uint8Array(buffer);
for (let i = 0; i < bytes.byteLength; i++) {
binary += String.fromCharCode(bytes[i]);
}
return window.btoa(binary);
}
static async sendContent(app, webhookUrl, content, filename, notePath) {
if (!this.validateUrl(webhookUrl)) {
throw new Error('Invalid webhook URL format');
}
const { frontmatter, content: noteContent } = this.parseYamlFrontmatter(content);
const attachments = await this.getAttachments(app, content, notePath);
const payload = {
...frontmatter,
content: noteContent,
filename,
timestamp: Date.now(),
attachments
};
try {
const response = await fetch(webhookUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload)
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return true;
} catch (error) {
throw new Error(`Failed to send webhook: ${error.message}`);
}
}
}
module.exports = { WebhookService };