Skip to content

Instantly share code, notes, and snippets.

@kevbost
Last active September 1, 2024 21:39
Show Gist options
  • Save kevbost/3b2806d56dc084e6a4ec9a420cced359 to your computer and use it in GitHub Desktop.
Save kevbost/3b2806d56dc084e6a4ec9a420cced359 to your computer and use it in GitHub Desktop.
Instagram Contest Winner Picker - https://kevinbost.com/instagram_giveaway/
/* eslint-disable no-var,newline-before-return */
var removeDuplicates = true
/**
* This function should work for any instagram post.
* Use it by opening Chrome's javascript console and pasting all of this code. (see link below)
* https://developers.google.com/web/tools/chrome-devtools/console/
*
* All comments are not immediately visible. This will automatically click the "show more" button for you.
* It could take some time depending on how many comments there are.
* Just wait, it cant go any faster using this method. ( the 250 interval is for the loading spinner, dont judge me )
* Once all comments have been made available, it will then choose a random commenter by username.
*
* Math.random() creates a random number between 0 & 1
* Multiply that random number by how many comments exist
* Round that new number down using Math.floor()
* Return the person at position people[ randomNumber ]
*
* For the sticklers out there, the reason this is so convoluted is for validation and message handling.
* It's users aren't programmers, instructions are logged if there is an error.
*
*/
var debug = false
var loadMoreButtonSelector = '[aria-label="Load more comments"]'
var loadingSvgSelector = 'article svg'
var userNameSelector = 'body > div#react-root > section > main article li h3'
var scrollContainerSelector = 'body > div#react-root > section > main article ul'
var errorStyle = 'background: red; color: white; font-size: x-large'
var infoStyle = 'background: green; color: white; font-size: x-large'
var warningStyle = 'background: green; color: white; font-size: large'
var successStyle = 'background: #ffd052; color: black; font-size: x-large'
var counter = '-'
var commentCount = 0
var prevCommentCount = 0
var loadingCount = 0
var tickCount = 0
var loadingLimitBreak = 30
var urlSinglePost = /(com\/p\/.*)/
var { log } = console
var { clear } = console
var clearConsole = () => {
!debug ? clear() : null
}
var reset = ( name ) => {
clearInterval( name )
clearConsole()
}
var loadingSpinner = () => {
counter==='-'?counter='/':counter==='/'?counter='- ':counter==='- '?counter='\\':counter==='\\'&&( counter='-' )
log( `Comments: ${commentCount}` )
!debug && log( `Loading... ${counter}` )
}
var interval = setInterval( () => {
const articleLength = document.querySelectorAll( 'article' ).length
const commentLength = document.querySelectorAll( userNameSelector ).length
const button = document.querySelector( loadMoreButtonSelector )
const loadingSvg = document.querySelectorAll( loadingSvgSelector )
const testedUrlBool = urlSinglePost.test( window.location.href )
const scrollContainer = document.querySelector( scrollContainerSelector )
if ( debug ) {
log({
articleLength,
commentLength,
button,
loadingSvg,
testedUrlBool,
scrollContainer
})
}
prevCommentCount = commentLength
scrollContainer ? scrollContainer.scrollTop = scrollContainer.scrollHeight : null
tickCount++
if ( testedUrlBool && articleLength > 1 ) {
reset( interval )
return log( '%cPlease reload the page to isolate the image, then re-run the script.', infoStyle )
} else if ( testedUrlBool && commentLength === 0 ) {
reset( interval )
return makeFunOfScriptRunner()
} else if ( articleLength > 1 || commentLength === 0 ) {
reset( interval )
log( '%cThis script only works on isolated images, please navigate directly to a single image', errorStyle )
return log( '%cFor example:\nhttps://www.instagram.com/p/BRWAyEQjEeB/', 'font-size: x-large' )
} else if ( window.innerWidth < 736 ) {
reset( interval )
return log( '%cSo this is a weird quirk you\'ve somehow found. The comments aren\'t visible at this screen width. Make your browser window a little bigger and try again.', infoStyle )
} else if ( loadingSvg.length && loadingCount < loadingLimitBreak ) {
loadingCount++
clearConsole()
loadingSpinner()
return
} else if ( button && prevCommentCount !== commentCount ) { // check if the new comment button is stuck
loadingCount = 0
tickCount = 0
clearConsole()
loadingSpinner() // super cool loading spinner, dont judge me
commentCount = commentLength
return button.click()
} else if ( debug && tickCount <= 10 ) {
return log( 'DEBUG', {
tickCount: tickCount,
loadingCount: loadingCount,
button: Boolean( button ),
prevCommentCount: prevCommentCount,
commentCount: commentCount,
'button && prevCommentCount !== commentCount': button && prevCommentCount !== commentCount
})
} else {
reset( interval )
return isolateUsernames( [ ...document.querySelectorAll( userNameSelector ) ] )
}
}, 250 )
var isolateUsernames = ( peopleList ) => {
let userNames = []
peopleList.map( x => {
if ( x.innerText !== document.querySelector( 'h2 a' ).innerText ) {
userNames.push( x.innerText )
}
})
if ( removeDuplicates ) {
const uniqueList = [ ...new Set( userNames ) ]
return uniqueList.length ? pickWinner( uniqueList, userNames.length ) : makeFunOfScriptRunner()
} else {
return userNames.length ? pickWinner( userNames, userNames.length ) : makeFunOfScriptRunner()
}
}
var randVideo = () => {
const items = [
'https://youtu.be/31j4DIpgY9U', // ghostmane mercury
'https://youtu.be/vXXHISsnQl4', // lary's barleywine
'https://youtu.be/kCaf9rWYmAg', // bilmuri there
'https://youtu.be/CEVXcP3VC3Y', // tyler igors theme
'https://youtu.be/9AXXSa8YEic', // the decline (live)
'https://youtu.be/LYWpFs8Na9k', // badcop+badcop womanarchist
'https://youtu.be/urt88eX5yXo?t=1859', // earth crisis (live)
'https://youtu.be/bN0ciI2Fibo?t=505' // earth crisis (punk rock mba)
]
return items[~~( items.length * Math.random() )]
}
var makeFunOfScriptRunner = () => {
log( '%cSeriously?', errorStyle )
log( '%cThere are clearly no comments.', errorStyle )
return log( `%c${randVideo()}`, 'font-size: x-large' )
}
var pickWinner = ( people, totalComments ) => {
// pick the winner! peow peow peeooowwww
const num = people.length
const WINNER = people[Math.floor( Math.random()*num )]
const button = document.querySelector( loadMoreButtonSelector )
const loadingSvg = document.querySelectorAll( loadingSvgSelector )
reset( interval )
loadingCount >= loadingLimitBreak && log( '%cError: comments stopped loading properly, please review results.\n\nYou can most likely just paste the code again WITHOUT reloading.', errorStyle )
Boolean( button || loadingSvg.length ) && log( '%cWarning: button to load more comments is still visible. This is probably because of a bug where IG enters an inescapable infinite loop by loading the same comments over and over.\n\nRegardless, run the script again just to make sure (WITHOUT reloading).\n\nIf nothing changes or if it loads comments you\'ve seen before, use the winner output below.', warningStyle )
log( `${totalComments} total comments (excludes replies, includes duplicates)` )
log( removeDuplicates ? `${totalComments - people.length} duplicate commenters removed` : 'duplicates not removed' )
log( `%cAnd the randomly selected winner out of ${num} ${num === 1 ? 'entry' : 'entries'} is...\n\n${WINNER.toUpperCase()} !!!!`, successStyle )
log( `%chttps://www.instagram.com/${WINNER}/`, 'font-size: large' )
}
@zaki322
Copy link

zaki322 commented Apr 4, 2020

I need a script to build website Instagram random comment picker

@kevbost
Copy link
Author

kevbost commented Apr 18, 2020

@zaki322

I need a script to build website Instagram random comment picker

Okay? Use this if it works for you.

The problem with building a random comment picker for Instagram is that the BEST way to do it is by using the Instagram API. That introduces new problems because the API key only allows you to interact with your own account -- not other users accounts without having them enter their own api key. <-- That's nonsense, so the next best thing is a scraper. On top of that, getting an API key for small projects is prohibitively difficult.

Just be aware that since this relies on a specific DOM structure, it can break at any time if Instagram decides to change the layout (see lines 25-28)

@JaycePak
Copy link

Completed running the code on the chrome, but below result comes, could you help me to solve this?

QUOTE
Console was cleared
5b0c34f88807.js:4 ErrorUtils caught an error:

Script error.

Subsequent non-fatal errors won't be logged; see https://fburl.com/debugjs.
errorListener @ 5b0c34f88807.js:4
reportNormalizedError @ 5b0c34f88807.js:4
reportError @ 5b0c34f88807.js:4
s @ 5b0c34f88807.js:4
error (async)
setup @ 5b0c34f88807.js:4
preSetup @ 5b0c34f88807.js:4
t @ 5b0c34f88807.js:2
e.entrypointReady @ 5b0c34f88807.js:2
(anonymous) @ 335fb44b350d.js:1
c @ (index):268
i @ (index):268
r @ (index):268
(anonymous) @ 335fb44b350d.js:1518
VM2617:107 Uncaught ReferenceError: removeDuplicates is not defined
at isolateUsernames (:107:3)
at :96:12
isolateUsernames @ VM2617:107
(anonymous) @ VM2617:96
setInterval (async)
(anonymous) @ VM2617:37
(index):53 Uncaught TypeError: Cannot read property 'push' of undefined
at window.onerror ((index):53)
window.onerror @ (index):53
error (async)
(anonymous) @ (index):52
(anonymous) @ (index):130
5b0c34f88807.js:82 Cross-Origin Read Blocking (CORB) blocked cross-origin response https://graph.instagram.com/logging_client_events with MIME type application/json. See https://www.chromestatus.com/feature/5629709824032768 for more details.
UNQUOTE

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment