Created
August 17, 2020 01:21
-
-
Save hobelinm/ce7ebdb0dc601a05542376eeb393e378 to your computer and use it in GitHub Desktop.
Calls Instagram oEmbed to insert Instagram posts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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