Skip to content

Instantly share code, notes, and snippets.

@hobelinm
Created August 17, 2020 01:21
Show Gist options
  • Save hobelinm/ce7ebdb0dc601a05542376eeb393e378 to your computer and use it in GitHub Desktop.
Save hobelinm/ce7ebdb0dc601a05542376eeb393e378 to your computer and use it in GitHub Desktop.
Calls Instagram oEmbed to insert Instagram posts
namespace AutoInstagram {
export class Control {
/**
* Find Instagram Id if passed via query parameter
*/
public static LoadFromParam(): string {
let url: URL = new URL(location.toString());
let instaId: string = url.searchParams.get(Constants.QuerySegment);
let instagramId: string = '';
if (instaId === null) {
// TODO: Instagram entry not found from query params
// Perform any backup plan here
} else {
instagramId = instaId;
}
return instagramId;
}
/**
* Takes API response and inserts the post's HTML into the page
* @param {iResponse} apiResponse Instagram's response message
* @param {string} target target text for the selector
*/
public static InsertInstagramPost(apiResponse: iResponse, target: string): void {
// Validate if the target can be located
let selection = $(AutoInstagram.Util.Format(AutoInstagram.Constants.DefaultSelector, [target]));
let selectorId: string = AutoInstagram.Util.Format(AutoInstagram.Constants.InstagramSelectorBase, [target]);
let setHtml: boolean = false;
if (selection.length === 0) {
// Probably there's an instagram post already...
selectorId = AutoInstagram.Util.Format(AutoInstagram.Constants.InstagramSelectorId, [selectorId]);
selection = $(selectorId);
if (selection.length === 0) {
// TODO: Selector not found message, perform any backup plan here
setHtml = false;
}
// Replacing an existing instagram post
setHtml = true;
} else {
setHtml = true;
}
if (setHtml) {
let postHtml: string = AutoInstagram.Util.Format(
AutoInstagram.Constants.HtmlContainer,
[
selectorId,
AutoInstagram.Constants.PostWidth.toString(),
apiResponse.html
]
);
selection.html(postHtml);
(<any>window).instgrm.Embeds.process();
}
}
/**
* Calls Instagram API to get the required HTML to insert in our page, then call InsertInstagramPost
* to update the page
* @param {string} postId Instagram post ID
* @param {string} targetSelector jQuery selector for the element to replace in the website
*/
public static QueryAndAddInstagramPost(postId: string, targetSelector: string): void {
let apiRequestUrl: string = LocalConstants.buildRequest(postId);
let oReq = new XMLHttpRequest();
oReq.responseType = "json";
oReq.onreadystatechange = () => {
if (oReq.readyState === XMLHttpRequest.DONE) {
AutoInstagram.Control.InsertInstagramPost(<AutoInstagram.iResponse>oReq.response, targetSelector);
} else {
// TODO: Error during the request perform any backup plan here
}
}
oReq.open('GET', apiRequestUrl);
oReq.send();
}
}
export class Storage {
public static InstagramAPIReq: XMLHttpRequest;
}
export class Constants {
public static readonly QuerySegment: string = "insta";
public static readonly DefaultTSelText: string = "Instagram-Auto-Embed";
public static readonly DefaultSelector: string = `p:contains('{0}')`;
// This could also be: Math.floor(Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0) * 0.9);
public static readonly PostWidth: number = 700;
public static readonly HtmlContainer: string = '<div id="{0}" style="display: block; margin-left: auto; margin-right: auto; width: {1}px;" >{2}</div>';
public static readonly InstagramSelectorBase: string = 'targetInsta-{0}';
public static readonly InstagramSelectorId: string = "div[id='{0}']";
}
export class Util {
public static Remove(base: string, matcher: string): string {
return base.replace(matcher, '');
}
public static Contains(base: string, matcher: string): boolean {
if (base.indexOf(matcher) !== -1) {
return true;
}
return false;
}
/**
* Formats a text by performing position based replacing at runtime
* @param {string} base Text that will be formatted
* @param {Array<string>} formatters Items to replace with
* @example Format("The {0} is {1} {2}", ["sun", "shinning", "today"]) returns: "The sun is shinning today"
*/
public static Format(base: string, formatters: Array<string>): string {
let index: number = 0;
formatters.forEach(formatter => {
let replaceToken: string = `{${index}}`;
base = base.replace(replaceToken, formatter);
index++;
});
return base;
}
/**
* Removes unsupported characters from text so it can be used as id
* @param raw entry to curate
*/
public static CurateId(raw: string): string {
return raw.replace(' ', '');
}
}
// Outlines the response object that is obtained after calling Instagram API
export interface iResponse {
version: number;
author_name: string;
provider_name: string;
provider_url: string;
type: string;
width: number;
html: string;
thumbnail_url: string;
thumbnail_width: number;
thumbnail_height: number;
}
class LocalConstants {
public static ReqUrl: string = `https://graph.facebook.com/v8.0/instagram_oembed?url=https://www.instagram.com/p/`;
public static AppTok: string = '<YOUR_APPLICATION_TOKEN_HERE>';
public static CliTok: string = '<YOUR_APPLICATION_CLIENT_TOKEN_HERE>';
public static buildRequest(postId: string): string {
return `${LocalConstants.ReqUrl}${postId}/&access_token=${LocalConstants.AppTok}|${LocalConstants.CliTok}`;
}
}
}
if ((<any>window).AutoInstagram === undefined) {
(<any>window).AutoInstagram = AutoInstagram;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment