Skip to content

Instantly share code, notes, and snippets.

@crutchcorn
Last active July 22, 2021 10:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save crutchcorn/f3fca48a0468f9df983cc99f3ea8c86e to your computer and use it in GitHub Desktop.
Save crutchcorn/f3fca48a0468f9df983cc99f3ea8c86e to your computer and use it in GitHub Desktop.
data.data.allMarkdownRemark.nodes.filter(md => md.frontmatter.license.id !== 'coderpad').map(md => ({
title: md.frontmatter.title,
slug: "https://unicorn-utterances.com/posts" + md.fields.slug,
year: (new Date(md.frontmatter.published)).getFullYear(),
day: (new Date(md.frontmatter.published)).getDate(),
month: (new Date(md.frontmatter.published)).getMonth(),
}))
query BlogListPageQuery {
allMarkdownRemark(
filter: {frontmatter: {authors: {elemMatch: {id: {eq: "crutchcorn"}}}}}
) {
nodes {
frontmatter {
title
license {
id
}
published
}
fields {
slug
}
}
}
}
// Start at profile page
// EG: https://www.polywork.com/crutchcorn/
const wait = (time) => new Promise(resolve => {
setTimeout(() => {
resolve();
}, time);
});
const waitFor = async (cb, maxWait = 5000) => {
let remainingTime = maxWait;
while (remainingTime > 0) {
const val = cb();
remainingTime -= 100;
if (!val) {
await wait(100);
} else {
return val;
}
}
};
const waitAndClick = async (cb) => {
const el = await waitFor(cb);
el.click();
};
const monthArr = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
const blogName = "Unicorn Utterances";
for (const blogPost of blogPosts) {
await submitPost(blogPost);
}
async function submitPost(blogInfo) {
const postBtn = await waitFor(() => document.querySelector("[href$=\"/highlights/new\"]"));
postBtn.click();
const selectEditModal = () => waitFor(() => document.querySelector("[id^=\"edit_draft_highlight\"]"));
let modal = await selectEditModal();
// Select date
// ********************************************************************************************************************
await (async () => {
const datePicker = await waitFor(() => modal.querySelector("[id=\"highlight-date-picker\"]"));
datePicker.click();
const pickerEditBtn = await waitFor(() => modal.querySelector("[data-action=\"click->highlight-date#showDatePicker\"]"));
pickerEditBtn.click();
// Year picker
await waitAndClick(() => modal.querySelector(".datepicker-switch"));
// Wait for calendar to show up
await waitFor(() => modal.querySelector(".datepicker-years .year"));
let yearBtn = null;
let attemptedYears = 0;
while (!yearBtn && attemptedYears < 10) {
yearBtn = [...modal.querySelectorAll(".year:not(.disabled)")].find(year => year.innerText === blogInfo.year.toString());
attemptedYears += 1;
if (!yearBtn) {
await waitAndClick(() => modal.querySelector(".prev"));
}
}
yearBtn.click();
let monthBtn = null;
let attemptedMonths = 0;
while (!monthBtn && attemptedMonths < 10) {
const monthName = monthArr[blogInfo.month];
monthBtn = [...modal.querySelectorAll(".month:not(.disabled)")].find(month => month.innerText === monthName);
attemptedMonths += 1;
if (!monthBtn) {
await waitAndClick(() => modal.querySelector(".prev"));
}
}
monthBtn.click();
let dayBtn = null;
let attemptedDays = 0;
while (!dayBtn && attemptedDays < 10) {
dayBtn = [...modal.querySelectorAll(".day:not(.new):not(.old)")].find(day => day.innerText === blogInfo.day.toString());
attemptedDays += 1;
if (!dayBtn) {
await waitAndClick(() => modal.querySelector(".prev"));
}
}
dayBtn.click();
})();
// ********************************************************************************************************************
// Set editor value
// ********************************************************************************************************************
const editor = await waitFor(() => modal.querySelector("[id=\"draft_highlight_content\"]"));
editor.value = `
I wrote an article!
${blogInfo.title}
${blogInfo.slug}
`.trim().replace(/\n/g, "<br>");
// ********************************************************************************************************************
// Set position
// ********************************************************************************************************************
await (async () => {
await waitAndClick(() => modal.querySelector("[formaction$=\"highlight_position\"]"));
modal = await waitFor(() => document.querySelector("[id=\"highlight_position_modal\"]"));
// Opens a new modal. Must reload old modal after selection
const positions = await waitFor(() => {
const els = modal.querySelectorAll("[for^=\"highlight-position\"]");
return els.length ? [...els] : null;
});
positions.find(e => e.innerText.includes(blogName)).click();
await waitAndClick(() => modal.querySelector("[type=\"submit\"]"));
modal = await selectEditModal();
})();
// ********************************************************************************************************************
// Set tags
// ********************************************************************************************************************
await (async () => {
const collapseSuggestionsBtn = await waitFor(() => modal.querySelector("[href=\"#collapseActivitySuggestions\"]"));
if (collapseSuggestionsBtn.ariaExpanded === "true") {
collapseSuggestionsBtn.click();
}
await waitAndClick(() => modal.querySelector("[formaction$=\"highlight_activities\"]"));
// Opens a new modal. Must reload old modal after selection
modal = await waitFor(() => document.querySelector("[id=\"highlight_activity_search_modal\"]"));
const findTagAndSelect = async (tagName) => {
const activitySearch = await waitFor(() => {
const formEl = modal.querySelector("[action$=\"/highlight_activities/search\"]");
return formEl && formEl.querySelector("input");
});
activitySearch.value = tagName;
activitySearch.dispatchEvent(new FocusEvent("focusin"));
const tagList = await waitFor(() => {
const els = modal.querySelectorAll("[href$=\"/tag\"].list-item-wrapper");
return els.length ? [...els] : null;
});
const tag = tagList.find(el => el.innerText.replace(/\s+/g, " ") === tagName);
tag.click();
};
await findTagAndSelect("Wrote an article");
await findTagAndSelect("Contributed to open source");
await waitAndClick(() => modal.querySelector("[form=\"tagged_activities_form\"][type=\"submit\"]"));
modal = await selectEditModal();
})();
// ********************************************************************************************************************
// Submit post
// ********************************************************************************************************************
await waitAndClick(() => modal.querySelector("[value=\"Post\"]"));
await waitAndClick(() => {
const tmpModal = document.querySelector("#highlight_success_share_modal");
const close = tmpModal && tmpModal.querySelector("[aria-label=\"Close\"]");
return close;
});
// ********************************************************************************************************************
}
// Months are zero indexed. Should be fine
var blogPosts = [{
"title": "Better Angular Form Components with ngModel and formControl Implementation",
"slug": "https://unicorn-utterances.com/posts/angular-components-control-value-accessor/",
"year": 2020,
"day": 9,
"month": 5
}, {
"title": "Package Font Files on NPM for Angular Usage",
"slug": "https://unicorn-utterances.com/posts/angular-npm-font-usage/",
"year": 2020,
"day": 24,
"month": 10
}, {
"title": "Networking 101: A Basic Overview of Packets and OSI",
"slug": "https://unicorn-utterances.com/posts/basic-overview-of-packets-and-osi/",
"year": 2020,
"day": 11,
"month": 2
}, {
"title": "Write Simpler Tests - 5 Suggestions for Better Tests",
"slug": "https://unicorn-utterances.com/posts/five-suggestions-for-simpler-tests/",
"year": 2020,
"day": 25,
"month": 4
}, {
"title": "Draw under the Android NavBar Using React Native",
"slug": "https://unicorn-utterances.com/posts/draw-under-navbar-using-react-native/",
"year": 2020,
"day": 15,
"month": 3
}, {
"title": "Setup Android Studio Emulator for AMD Ryzen CPUs",
"slug": "https://unicorn-utterances.com/posts/android-studio-setup-for-ryzen-cpus/",
"year": 2020,
"day": 5,
"month": 4
}, {
"title": "Data Storage Options for React Native",
"slug": "https://unicorn-utterances.com/posts/data-storage-options-in-react-native/",
"year": 2020,
"day": 13,
"month": 3
}, {
"title": "Debugging NodeJS Applications Using Chrome",
"slug": "https://unicorn-utterances.com/posts/debugging-nodejs-programs-using-chrome/",
"year": 2020,
"day": 20,
"month": 0
}, {
"title": "How to Pick Tech Stacks For New Projects",
"slug": "https://unicorn-utterances.com/posts/how-to-pick-tech-stacks-for-new-projects/",
"year": 2020,
"day": 1,
"month": 2
}, {
"title": "WebDev 101: How to use npm and Yarn",
"slug": "https://unicorn-utterances.com/posts/how-to-use-npm/",
"year": 2021,
"day": 5,
"month": 3
}, {
"title": "How Computers Speak: Assembly to AST",
"slug": "https://unicorn-utterances.com/posts/how-computers-speak/",
"year": 2020,
"day": 24,
"month": 7
}, {
"title": "Integrating Native Android Code in Unity",
"slug": "https://unicorn-utterances.com/posts/integrating-android-code-in-unity/",
"year": 2020,
"day": 3,
"month": 0
}, {
"title": "Introduction to TypeScript — What is TypeScript?",
"slug": "https://unicorn-utterances.com/posts/introduction-to-typescript/",
"year": 2019,
"day": 12,
"month": 9
}, {
"title": "Building an Angular Blog With Scully",
"slug": "https://unicorn-utterances.com/posts/making-an-angular-blog-with-scully/",
"year": 2020,
"day": 16,
"month": 2
}, {
"title": "Making a Slack Bot using NodeJS and MongoDB",
"slug": "https://unicorn-utterances.com/posts/making-a-slack-bot-with-node-and-mongo/",
"year": 2020,
"day": 17,
"month": 1
}, {
"title": "Networking 101: UDP & TCP",
"slug": "https://unicorn-utterances.com/posts/networking-101-udp-and-tcp/",
"year": 2020,
"day": 30,
"month": 2
}, {
"title": "How Binary and Hexadecimal Work: An introduction to non-decimal number systems",
"slug": "https://unicorn-utterances.com/posts/non-decimal-numbers-in-tech/",
"year": 2019,
"day": 6,
"month": 10
}, {
"title": "React Refs: The Complete Story",
"slug": "https://unicorn-utterances.com/posts/react-refs-complete-story/",
"year": 2020,
"day": 30,
"month": 10
}, {
"title": "Understanding The DOM: How Browsers Show Content On-Screen",
"slug": "https://unicorn-utterances.com/posts/understanding-the-dom/",
"year": 2019,
"day": 26,
"month": 10
}, {
"title": "Autogenerate Changelogs and Manage Releases using Conventional Commit",
"slug": "https://unicorn-utterances.com/posts/setup-standard-version/",
"year": 2020,
"day": 22,
"month": 5
}, {
"title": "TypeScript Intermediates - Type Generics",
"slug": "https://unicorn-utterances.com/posts/typescript-type-generics/",
"year": 2019,
"day": 25,
"month": 8
}, {
"title": "Uttering Hello — The Site's First Post",
"slug": "https://unicorn-utterances.com/posts/uttering-hello-introduction-post/",
"year": 2019,
"day": 29,
"month": 5
}, {
"title": "The Ultimate Windows Development Environment Guide",
"slug": "https://unicorn-utterances.com/posts/ultimate-windows-development-environment-guide/",
"year": 2020,
"day": 6,
"month": 3
}, {
"title": "Adding Cathage Dependencies into React Native",
"slug": "https://unicorn-utterances.com/posts/using-carthage-with-react-native/",
"year": 2020,
"day": 13,
"month": 9
}, {
"title": "What is Server Side Rendering (SSR) and Static Site Generation (SSG)?",
"slug": "https://unicorn-utterances.com/posts/what-is-ssr-and-ssg/",
"year": 2020,
"day": 23,
"month": 2
}, {
"title": "Angular Templates — From Start to Source",
"slug": "https://unicorn-utterances.com/posts/angular-templates-start-to-source/",
"year": 2019,
"day": 11,
"month": 6
}, {
"title": "GitHub Copilot is Amazing - It Won't Replace Developers",
"slug": "https://unicorn-utterances.com/posts/github-copilot-wont-replace-devs/",
"year": 2021,
"day": 30,
"month": 4
}];
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment