Action

Post/Update to Micro.blog (test)

Posted by donnydavis, Last update about 1 month ago - Unlisted

Post to your Micro.blog hosted blog.

If you have multiple blogs, then you can select which one to post to. You can select if you would like to create a draft or publish directly. You can also select which, if any, categories to add.

If you would like a title for your post then add a # to the first line. Otherwise it will post without a title.

Posting options that are available:
* Setting the post status.
* Selecting cross posting targets.
* Selecting categories.

After posting, whether it’s a draft or published, you can use this action to update the post as well. To make this happen, there are tags added to the draft that contain the domain that it is posted to and the post slug. If these are removed then it will create a new post. There is also a tag added that reflects the post status, if it is a draft or published.

Steps

  • script

    // Post to Micro.blog Hosted Blog
    // Define classess and objects.
    
    // Main client that contains the app token and
    // the base request parameters.
    
    class MBClient {
    
    	// Public properties
    	
    	domains = [];
    	categories = [];
    	
    	get post() {
    		return this.#_post;
    	}
    	set post(newValue) {
    		this.#_post = newValue;
    		if (this.post.selectedDomain.length > 0) {
    			this.#getAllCategories();
    		}
    		if (this.post.isUpdating) {
    			this.#getPostProperties();
    		}
    	}
    
    	// Private properties
    
    	#appToken;
    	#_post;
    
    	constructor(appToken) {
    		this.#appToken = appToken;
    		this.post = new Post();
    		this.#getConfigValues();
    	}
    
    	// Public methods
    	
    	setSelectedDomain(selectedDomain) {
    		this.post.selectedDomain = selectedDomain;
    		this.#getAllCategories();
    	}
    		
    	sendPost() {
    		let additionalParameters= {};
    		if (this.post.isUpdating) {
    			additionalParameters = this.post.updateParameters();
    		} else {
    			additionalParameters = this.post.createParameters();
    		}
    		
    		const response = this.#performRequest(additionalParameters);
    		
    		if (response.statusCode != 200 
    			&& response.statusCode != 202) {
    			console.log("Post failed with status code: " + response.statusCode);
    			context.fail("Post failed.");
    
    		} else {
    			this.#setPostMetaData(response.headers.Location);
    		}
    	}
    	
    	// Private methods
    	
    	#baseRequestParameters() {
    		return {
    			"url": "https://micro.blog/micropub",
    			"parameters": {},
    			"headers": {
    				"Authorization": "Bearer " + this.#appToken,
    			},
    		};
    	}
    	
    	#performRequest(additionalParameters) {
    		const parameters = {
    			...this.#baseRequestParameters(), 
    			...additionalParameters
    		};
    		const req = HTTP.create();
    		return req.request(parameters);
    	}
    	
    	#parseDomain(domain) {
    		let host = domain.uid.split("://")[0];
    		return host + "://" + domain.name;
    	}
    	
    	#getConfigValues() {
    		const response = this.#performRequest(
    			{
    				"method": "GET",
    				"parameters": {
    					"q": "config"
    				}
    			}
    		);
    		
    		if (response.statusCode != 200 
    			&& response.statusCode != 202) {
    			console.log("Request for list of domains failed. Status code: " + response.statusCode);
    			context.fail();
    		
    		} else if (typeof(response.responseData.destination) == "undefined") {
    			console.log("Response for initial config info returned with no data.");
    			context.fail();
    		
    		} else {
    			this.domains = response.responseData.destination
    				.map(this.#parseDomain);
    		
    			this.post.syndicateTo = response.responseData["syndicate-to"]
    				.map(target => target.uid.charAt(0).toUpperCase() + target.uid.slice(1));
    		}
    	}
    	
    	#getAllCategories() {
    		const response = this.#performRequest(
    			{
    				"method": "GET",
    				"parameters": {
    					"q": "category",
    				}
    			}
    		);
    		
    		console.log("Category Response Status: " + response.statusCode);
    		console.log("Categories Response Data: " + JSON.stringify(response.responseData));
    		console.log("Response error: " + response.error);
    		console.log("Headers: " + JSON.stringify(response.headers));
    	
    		if (response.statusCode != 200 
    			&& response.statusCode != 202) {
    			context.fail("Request for categories failed.");
    		
    		} else {
    			this.categories = response.responseData.categories;
    		}
    	}
    	
    	#getPostProperties() {
    		const response = this.#performRequest(
    			{
    				"method": "GET",
    				"parameters": {
    					"q": "source",
    					"mp-destination": this.post.selectedDomain,
    					"url": this.post.url,
    					"post-status": this.post.status.toLowerCase(),
    				}
    			}
    		);
    		
    		if (response.statusCode != 200 
    			&& response.statusCode != 202) {
    			console.log("Request for selected categories failed.");
    			context.fail();
    		
    		} else {
    			this.post.categories = response.responseData.properties.category;
    		
    			if (response.responseData.properties.published) {
    				this.post.publishedDate = new Date(response.responseData.properties.published);
    			}
    		}
    	}
    	
    	#setPostMetaData(url) {
    		if (this.post.isUpdating) {
    			draft.addTag(this.post.status.toLowerCase());
    			let postTag = draft.tags
    				.find(item => item.startsWith("post:"));
    			draft.removeTag(postTag);
    			
    		} else {
    			draft.addTag(this.post.status.toLowerCase());
    			draft.addTag("domain:" + this.post.selectedDomain);
    		}
    		let post = url.replace(this.post.selectedDomain + "/", "");
    		draft.addTag("post:" + post);
    	
    		draft.update();
    	}
    }
    
    // Class to contain post details
    
    class Post {
    
    	// Public properties
    	categories = [];
    	status = "Published";
    	publishedDate = new Date();
    	syndicateTo = [""];
    	title = "";
    	content = "";
    	selectedDomain = "";
    	
    	get url() {
    		if (this.selectedDomain.length > 1 && this.#slug.length > 1) {
    			return this.selectedDomain + "/" + this.#slug;
    		} else {
    			return "";
    		}
    	}
    	
    	get isUpdating() {
    		return this.url.length > 1;
    	}
    	
    	get isScheduled() {
    		const currentDate = new Date();
    		return publishedDate.getTime() > currentDate.getTime();
    	}
    
    	// Private properties
    	
    	#slug = "";
    	
    	constructor() {
    		this.#setCurrentDomain();
    		this.#setPostSlug();
    		this.#setPostStatus();
    		this.#setPostContent();
    	}
    	
    	// Private methods
    	
    	#setCurrentDomain() {
    		if (draft.tags.some(item => item.startsWith("domain:"))) {
    			this.selectedDomain = draft.tags
    				.find(item => item.startsWith("domain:"))
    				.replace("domain:", "");
    
    			const length = this.selectedDomain.length - 1;
    			if (this.selectedDomain[length] == "/") {
    				this.selectedDomain = this.selectedDomain.substring(0, length);
    			}
    		} else {
    			this.selectedDomain = "";
    		}
    	}
    	
    	#setPostSlug() {
    		if (draft.tags.some(item => item.startsWith("post:"))) {
    			this.#slug = draft.tags
    				.find(item => item.startsWith("post:"))
    				.replace("post:", "");
    		} else {
    			this.#slug = "";
    		}
    	}
    	
    	#setPostStatus() {
    		if (draft.tags.includes("draft")) {
    			this.status = "Draft";
    		} else {
    			this.status = "Published";
    		}
    	}
    	
    	#setPostContent() {
    		if (this.#hasTitle()) {
    	 		this.title = draft.processTemplate("[[safe_title]]");
    		 	this.content = draft.processTemplate("[[body]]");
    		} else {
    	 		this.content = draft.content;
    		}
    	}
    	
    	#hasTitle() {
    		const firstLine = draft.processTemplate("[[title]]");
    		return firstLine.startsWith("#");
    	}
    	
    	#formatSyndicateToValues(syndicateTo) {
    		if (syndicateTo.length) {
    			return syndicateTo.map(element => element.toLowerCase());
    		} else {
    			return [""];
    		}
    	}
    
    	// Public Properties
    	setPostProperties(prompt) {
    		if (prompt.fieldValues["postStatus"]) {
    			this.status = prompt.fieldValues["postStatus"].toString();
    		}
    		
    		const syndicateToValues = prompt.fieldValues["syndicateTo"];
    		if (Array.isArray(syndicateToValues)) {
    			this.syndicateTo = syndicateToValues;
    		}
    		
    		const categoryList = prompt.fieldValues["categories"];
    		if (categoryList) {
    			this.categories = categoryList;
    		}
    	
    		const publishDate = prompt.fieldValues["publishDate"];
    		if (publishDate) {
    			this.publishedDate = publishDate;
    		}
    	}
    	
    	createParameters() {
    		let requestParameters = {
    			"method": "POST",
    			"encoding": "form",
    			"parameters": {
    				"mp-destination": this.selectedDomain,
    			},
    			"data": {
    				"h": "entry",
    	 			"post-status": this.status.toLowerCase(),
    	 			"mp-syndicate-to": this.#formatSyndicateToValues(this.syndicateTo),
    		 		"content": this.content,
    		 		"category": this.categories,
    	 			"published": this.publishedDate,
    			}
    		};
    		
    		if (this.title.length > 0) {
    			requestParameters.data.name = this.title;
    		}
    		
    		return requestParameters;
    	}
    	
    	updateParameters() {
    		let requestParameters = {
    			"method": "POST",
    			"parameters": {
    				"mp-destination": this.selectedDomain,
    			},
    			"data": {
    				"action": "update",
    				"url": this.url,
    			 	"replace": {
    		 			"post-status": [this.status],
    		 			"content": this.content,
    		 			"category": this.categories,
    	 			}
    			}
    		};
    	 	
    	 	if (this.title.length > 0) {
    			requestParameters.data.replace.name = this.title;
    		}
    		
    		return requestParameters;
    	}
    }
    
  • script

    // Post to Micro.blog Hosted Blog
    // 
    // Prompt for app token and set up client.
    
    const credential = Credential.create("Micro.blog", "Insert Micro.blog app token generated on Micro.blog account page.");
    credential.addPasswordField("apptoken", "App Token");
    
    credential.authorize();
    
    const appToken = credential.getValue("apptoken").toString().trim();
    const micropubEndpoint = "https://micro.blog/micropub";
    
    let mbClient = new MBClient(appToken);
    
  • script

    // Post to Micro.blog Hosted Blog
    // 
    // Prompt for selected domain to post to.
    
    if (mbClient.post.isUpdating == false) {
    	promptForDomains();
    }
    
    // Prompt for a domain to post to
    function promptForDomains() {
    	let domains = mbClient.domains;
    	let prompt = Prompt.create();
    	prompt.title = "Micro.blog Post";
    	prompt.message = "Select domain to post to.";
    
    	if (domains.length > 1) {
    		let defaultDomain = domains[0];
    		prompt.addSelect("domain", "Domains", domains, [defaultDomain], false);
    		
    	} else if (domains.length == 1) {
    		mbClient.post.selectedDomain = domains[0];
    		return;
    		
    	} else {
    		console.log("No available domain to select from.");
    		context.fail();
    	}
    	
    	prompt.addButton("Next");
    	var promptResponse = prompt.show();
    	
    	if (promptResponse == false) {
    		console.log("Cancel button was pressed.");
    		context.fail();
    		
    	} else {
    		mbClient.setSelectedDomain(prompt.fieldValues["domain"].toString());
    	}
    }
    
  • script

    // Post to Micro.blog Hosted Blog
    // 
    // Prompt for posting options.
    
    promptForOptions();
    
    function promptForOptions() {	
    	let prompt = Prompt.create();
    	prompt.title = "Micro.blog Post";
    	prompt.message = "Select Posting Options";
    	
    	if (draft.hasTag("published") == false) {
    		let postStatuses = [
    			"Published",
    			"Draft"
    		]
    		prompt.addSelect("postStatus", "Post Status", postStatuses, [mbClient.post.status], false);
    		
    		if (mbClient.post.isUpdating == false) {
    			const defaultPublishDate = mbClient.post.publishedDate;
    			prompt.addDatePicker("publishDate", "Publish Date", defaultPublishDate, {
    				"minimumDate": new Date(),
    				"mode": "dateAndTime"
    			});
    		}
    	}
    	
    	if (mbClient.post.syndicateTo.length > 0 && mbClient.post.isUpdating == false) {
    		prompt.addSelect("syndicateTo", "Cross Posting", mbClient.post.syndicateTo, mbClient.post.syndicateTo, true);
    	}
    		
    	if (mbClient.categories.length > 0) {
    		prompt.addSelect("categories", "Categories", mbClient.categories, mbClient.post.categories, true);
    	}
    		
    	if (mbClient.post.isUpdating) {
    		prompt.addButton("Update");
    	} else {
    		prompt.addButton("Post");
    	}
    	const promptResponse = prompt.show();
    	
    	if (promptResponse == false) {
    		context.fail("User cancelled action");
    		
    	} else {
    		mbClient.post.setPostProperties(prompt);
    		mbClient.sendPost();
    	}
    }
    

Options

  • After Success Archive , Tags: blog
    Notification Info
    Log Level Info
Items available in the Drafts Directory are uploaded by community members. Use appropriate caution reviewing downloaded items before use.