Skip to content

Commit ce00c4d

Browse files
authored
* Updated permissions, as they seem to be sensible (#275)
to upper-lower-case (i.e.: "read" instead of "Read"). * Re-organized function order in the committed * Minor typos resolved
1 parent 9ab7467 commit ce00c4d

3 files changed

Lines changed: 124 additions & 119 deletions

File tree

publish-to-fediverse/info.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"script": "publish-to-fediverse.qml",
55
"authors": ["@77nnit"],
66
"platforms": ["linux", "windows"],
7-
"version": "0.2.0",
7+
"version": "0.3.0",
88
"minAppVersion": "24.11.0",
99
"description": "<p>Publish To Fediverse lets you publish your notes to your Mastodon-tish Fediverse Account.</p><p>This script works with servers that support Mastodon APIs, such as GoToSocial. If you test somenthing else let me know!</p><p>If you're looking for more detailed instructions to have this script work, please check the readme file in the script folder, or navigate to <a href='https://codeberg.org/77nn/QOwnNotes-personal-scripts/src/branch/main/publish-to-gts/readme.md'>my Codeberg's workshop</a>"
1010
}

publish-to-fediverse/publish-to-fediverse.qml

Lines changed: 122 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,125 @@ Script {
116116
msgText += `Press "<b>Cancel</b>" to continue editing your note.`;
117117
return (script.questionMessageBox(msgText, "P2F: confirm publishing", 0x00000400 | 0x00400000) == 1024);
118118
}
119-
function customActionInvoked(identifier) {
120119

120+
// This function generates a Post Header with comments and default parameter values for the current note.
121+
// if includeAdditional = true adds additional attributes (like created_at for already published notes)
122+
function generateFrontmatter(includeAdditional) {
123+
let frontMatter = "";
124+
frontMatter += "***Publish to Fediverse - frontmatter***\n";
125+
frontMatter += "\n";
126+
frontMatter += "#Edit the values to adjust the post settings.\n";
127+
frontMatter += "#Missing properties will be defaulted as per script settings.\n";
128+
frontMatter += "#Confirmation will be asked before publishing.\n";
129+
frontMatter += "#This section will not be published.\n";
130+
frontMatter += "\n";
131+
// checking all post parameters in currentParams against user settings params
132+
Object.keys(currentParams).forEach(function (key) {
133+
// using .every to break out the cycle
134+
settingsVariables.every(function (varObj) {
135+
if (key == varObj.identifier) {
136+
// the eval used here is safe, as the variable it evaluates contains always a string value.
137+
frontMatter += `${key}: ${eval(varObj.identifier)}${"\n"}`;
138+
return false;
139+
} else {
140+
return true;
141+
}
142+
});
143+
});
144+
if (includeAdditional) {
145+
Object.keys(additionalParams).forEach(function (key) {
146+
frontMatter += `${key}: ${additionalParams[key]}${"\n"}`;
147+
});
148+
}
149+
return frontMatter;
150+
}
151+
152+
// This function updates the Frontmatter found in a Post with current parameter values for the current note.
153+
function updateFrontmatter() {
154+
let current = script.currentNote();
155+
let sections = current.noteText.split("---");
156+
script.tagCurrentNote("P2F");
157+
if (sections && sections[1]) {
158+
script.triggerMenuAction("actionAllow_note_editing", 1);
159+
mainWindow.focusNoteTextEdit();
160+
script.noteTextEditSetCursorPosition(0);
161+
script.noteTextEditSelectAll();
162+
script.noteTextEditWrite([sections[0], ("---\n" + generateFrontmatter(true) + "\n---")].concat(sections.slice(2)).join(""));
163+
}
164+
}
165+
166+
// function that reads a Frontmatter section and populate the currentParams object
167+
function decodeFrontmatter(){
168+
let current = script.currentNote(); // current note
169+
let postParams = {};
170+
let sections = current.noteText.split("---");
171+
if (sections && sections[1]){
172+
sections[1].split("\n").forEach(function(param){
173+
if (! param.startsWith("#")){
174+
let thisParam = param.split(":");
175+
if (thisParam[0] && thisParam[1]){
176+
postParams[thisParam[0].trim()]=param.split(":").slice(1).join("").trim();
177+
}
178+
}
179+
});
180+
currentParams = postParams;
181+
return true;
182+
} else {
183+
script.log("P2F: Current note does not have a valid frontmatter.");
184+
return false;
185+
}
186+
}
187+
188+
// This function parses a string for bool values or returns the original string
189+
function parseBool(val) {
190+
if (Object.prototype.toString.call(val) == "[object String]") {
191+
return val == "true" ? true : (val == "false" ? false : val);
192+
} else {
193+
return val === true || val === "true";
194+
}
195+
}
196+
197+
// This function performs all API endpoint requests and returns text responses
198+
function request(verb, endpoint, aT, data) {
199+
// create request
200+
let xhr = new XMLHttpRequest();
201+
let url = "https://" + serverInstance + endpoint;
202+
// open synchronous request
203+
xhr.open(verb, url, false);
204+
// setting content type request header
205+
xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8");
206+
// is accessToken is provided in the function call adding the Authorization header
207+
if (aT && aT.length > 0) {
208+
xhr.setRequestHeader("Authorization", "Bearer " + aT);
209+
}
210+
// sending the request with data, if date is there
211+
if (data) {
212+
// xhr.setRequestHeader("Content-Length", JSON.stringify(data).length);
213+
xhr.send(JSON.stringify(data));
214+
} else {
215+
xhr.send();
216+
}
217+
// since tha call is synchronous at this poit we already have the response
218+
// the response body is returned
219+
if (xhr.status == 200) {
220+
return xhr.response;
221+
// If the request is nor completed with a success code 200, write to che console the error and return null
222+
} else {
223+
script.log("P2F: Error: " + serverInstance + endpoint + " returned code " + xhr.status + " - " + xhr.statusText);
224+
script.log (JSON.stringify(xhr.response));
225+
script.log (xhr.getAllResponseHeaders());
226+
return null;
227+
}
228+
}
229+
230+
// This function wraps the verify credential call
231+
function verifyCredentials(aT) {
232+
// calling the request over the specific endpoint, passing the accessToken
233+
let res = request("GET", "/api/v1/accounts/verify_credentials", aT);
234+
return res && true;
235+
}
236+
237+
function customActionInvoked(identifier) {
121238
//handler for newPost command
122239
if (identifier == "newPost") {
123240
let date = new Date();
@@ -135,7 +252,7 @@ Script {
135252
if (identifier == "publish") {
136253
// local variables init
137254
let clientName = "QONP2F";
138-
let clientMode = "Read Write Profile";
255+
let clientMode = "read write profile";
139256
let clientId = "";
140257
let clientSecret = "";
141258
let oobCode = "";
@@ -145,7 +262,7 @@ Script {
145262
let currentPost = ""; //current part of note that represents a post when frontmatter is stripped
146263
let instanceInfo = {};
147264
let maxCharsPerPost = 500; //default for Mastodon instances
148-
script.log("mysignature: " + mySignature);
265+
script.log("P2F: Applying signature to post - " + mySignature);
149266
if (!decodeFrontmatter()) {
150267
let exitCondition = true;
151268
let confirmResult = confirmFrontmatter();
@@ -196,7 +313,7 @@ Script {
196313

197314
// If authCode (accessToken) is stored on user settings, recover and authenticate with it
198315
if (accessToken && accessToken.length > 0) {
199-
// authorization conde was found, verifying credentials
316+
// authorization code was found, verifying credentials
200317
credentialsVerified = verifyCredentials(accessToken);
201318
} else {
202319
// start oob registering process
@@ -294,60 +411,7 @@ Script {
294411
return;
295412
}
296413
}
297-
298-
// function that reads a Frontmatter section and populate the currentParams object
299-
function decodeFrontmatter() {
300-
let current = script.currentNote(); // current note
301-
let postParams = {};
302-
let sections = current.noteText.split("---");
303-
if (sections && sections[1]) {
304-
sections[1].split("\n").forEach(function (param) {
305-
if (!param.startsWith("#")) {
306-
let thisParam = param.split(":");
307-
if (thisParam[0] && thisParam[1]) {
308-
postParams[thisParam[0].trim()] = param.split(":").slice(1).join("").trim();
309-
}
310-
}
311-
});
312-
currentParams = postParams;
313-
return true;
314-
} else {
315-
script.log("P2F: Current note does not have a valid frontmatter.");
316-
return false;
317-
}
318-
}
319-
320-
// This function generates a Post Header with comments and default parameter values for the current note.
321-
// if includeAdditional = true adds additional attributes (like created_at for already published notes)
322-
function generateFrontmatter(includeAdditional) {
323-
let frontMatter = "";
324-
frontMatter += "***Publish to Fediverse - frontmatter***\n";
325-
frontMatter += "\n";
326-
frontMatter += "#Edit the values to adjust the post settings.\n";
327-
frontMatter += "#Missing properties will be defaulted as per script settings.\n";
328-
frontMatter += "#Confirmation will be asked before publishing.\n";
329-
frontMatter += "#This section will not be published.\n";
330-
frontMatter += "\n";
331-
// checking all post parameters in currentParams against user settings params
332-
Object.keys(currentParams).forEach(function (key) {
333-
// using .every to break out the cycle
334-
settingsVariables.every(function (varObj) {
335-
if (key == varObj.identifier) {
336-
// the eval used here is safe, as the variable it evaluates contains always a string value.
337-
frontMatter += `${key}: ${eval(varObj.identifier)}${"\n"}`;
338-
return false;
339-
} else {
340-
return true;
341-
}
342-
});
343-
});
344-
if (includeAdditional) {
345-
Object.keys(additionalParams).forEach(function (key) {
346-
frontMatter += `${key}: ${additionalParams[key]}${"\n"}`;
347-
});
348-
}
349-
return frontMatter;
350-
}
414+
351415
function init() {
352416
script.registerCustomAction("publish", "Publish to Fediverse", "", true, true, false);
353417
script.registerCustomAction("newPost", "New post for Fediverse", "", true, true, false);
@@ -358,64 +422,5 @@ Script {
358422
}
359423
}
360424

361-
// This function returns a true or a false or a string that doesn't match true or false
362-
function parseBool(val) {
363-
if (Object.prototype.toString.call(val) == "[object String]") {
364-
return val == "true" ? true : (val == "false" ? false : val);
365-
} else {
366-
return val === true || val === "true";
367-
}
368-
}
369-
370-
// This function performs all API endpoint requests and returns text responses
371-
function request(verb, endpoint, aT, data) {
372-
// create request
373-
let xhr = new XMLHttpRequest();
374-
let url = "https://" + serverInstance + endpoint;
375-
// open synchronous request
376-
xhr.open(verb, url, false);
377-
// setting content type request header
378-
xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8");
379-
// is accessToken is provided in the function call adding the Authorization header
380-
if (aT && aT.length > 0) {
381-
xhr.setRequestHeader("Authorization", "Bearer " + aT);
382-
}
383-
// sending the request with data, if date is there
384-
if (data) {
385-
// xhr.setRequestHeader("Content-Length", JSON.stringify(data).length);
386-
xhr.send(JSON.stringify(data));
387-
} else {
388-
xhr.send();
389-
}
390-
// since tha call is synchronous at this poit we already have the response
391-
// the response body is returned
392-
if (xhr.status == 200) {
393-
return xhr.response;
394-
// If the request is nor completed with a success code 200, write to che console the error and return null
395-
} else {
396-
script.log("P2F: Error: " + serverInstance + endpoint + " returned code " + xhr.status + " - " + xhr.statusText);
397-
//script.log (JSON.stringify(xhr.response));
398-
//script.log (xhr.getAllResponseHeaders());
399-
return null;
400-
}
401-
}
402-
function updateFrontmatter() {
403-
let current = script.currentNote();
404-
let sections = current.noteText.split("---");
405-
script.tagCurrentNote("P2F");
406-
if (sections && sections[1]) {
407-
script.triggerMenuAction("actionAllow_note_editing", 1);
408-
mainWindow.focusNoteTextEdit();
409-
script.noteTextEditSetCursorPosition(0);
410-
script.noteTextEditSelectAll();
411-
script.noteTextEditWrite([sections[0], ("---\n" + generateFrontmatter(true) + "\n---")].concat(sections.slice(2)).join(""));
412-
}
413-
}
414425

415-
// This function wraps the "verify credential" call
416-
function verifyCredentials(aT) {
417-
// calling the request over the specific endpoint, passing the accessToken
418-
let res = request("GET", "/api/v1/accounts/verify_credentials", aT);
419-
return res && true;
420-
}
421426
}

publish-to-fediverse/readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ Here the process splits, depending on the authentication mechanism your instance
5858

5959
- Application name: `QONP2F`
6060
- Redirect URI: ensure it is set to `urn:ietf:wg:oauth:2.0:oob`
61-
- Scopes: check`Read`, `Write` and `Profile`
61+
- Scopes: check`read`, `write` and `profile`
6262

6363
3. Confirm and save the changes
6464
4. Copy the freshly generated `Your access token` value and paste it in the Script setting `Authorization Code` on QON.

0 commit comments

Comments
 (0)