Created
August 27, 2024 06:59
-
-
Save notarikon-nz/45432df01e9aefc1c73636cfb391fc9d to your computer and use it in GitHub Desktop.
HackMUD T1 Scraper - Including Projects, Employee Pages & Control Panels
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
| function(context, args) {// t:#s.weyland.public | |
| let corp_list = "amal_robo.public,aon.public,archaic.public,bluebun.public,bunnybat_hut.public,context.public,core.public,cyberdine.public,empty_nest.public,etceteraco.public,futuretech.public,goodfellow.public,halperyon.public,kill_9_1.public,kill_bio.public,legion_bible.public,legion_intl.public,light.public,lowell_extermination.public,marco_polo.public,merrymoor_pharma.public,nation_of_wales.public,nogrub.public,nuutec.public,pica.public,protein_prevention.public,ros_13_update_checker.public,ros13.public,setec_gas.public,skimmerite.public,sn_w.public,soylentbean.public,subject_object.public,suborbital_airlines.public,tandoori.public,the_holy_checksum.public,turing_testing.public,tyrell.public,vacuum_rescue.public,weathernet.public,welsh_measles_info.public,weyland.public,world_pop.public".split(",") | |
| if (args && args.portal && !args.t) { | |
| return corp_list.join("\n") | |
| } | |
| if (!args) { | |
| // const t1List = #fs.nuka_cola.status().substring(51); | |
| return "\n`HAPERTURE SCIENCE TIER 1`\n\nUsage: aperture.t1 { t:#s.corp.name }" + "\n\n" + "Available corps:\n\n" + printColumns(corp_list, context.cols) | |
| } | |
| let projs = "__av93zk9b9,Ap_calypse,BL4Z1NGW0RLD,cloudskimmer.da7a,delete_me_first,dsktp_mngr,ende.exe,ESCHATOLOGI.EXE,forgetme_nt,Free_BFG,giant_spidr,H0meEntert4inment,judgeme_nt,ls_rites,LUNARLANDER_01.11.bat,omegabyte_03.23_final_final,qw_stop,ragnaroxx.sh,semordnilap.sh,semordnilap.sh,thefloood,tmp,Vy_for_russ,W3rlD3NDER,dev_nul".split(",") | |
| let users = "_123lt_jack,_3rd_3y3_grill,3rd_3y3_grill,ad4m4,ada_love,aeryn_s,amelie,arr_too_d_to,b_sisko,b3nd3r,b4cca,b4rry_vv,bassy_thecount,be_lavar,bella_swan,bella_swann,boba_the_hutt,bobranator,boris,brohda_99,bus_and_parks,c_vader,carrie_on_,catness,chad_bose,cheechfiend91,childishg4mb,cking,computer_blue,corg_train,corgitruthsayer,crichton_j,curtfields0fmay,d_bowman,d_jackson,d4ft,d4ria,daa_freak,daurmith,delete_me_first,derek_zoo,diamond_dogz,do_u_need_hal,doc_brown,dr00gy_lex,du_boyz,duke_ell,e_ponine,etceteraco,firebreathingdragon,foxy_guy,frank_einstein,frantimike,free_man_morg,geyser_sore,geyser_soze,ginnypig,gwashc,h_jimi,h4chguy,hand_solo,hermione,htubman,huey_n,hypati4_370,i_am_the_eggman,ice_ventura,indie_jones,inigo,ireneadler,jack_sparrow,jamesb,janeway,jermaine,jim_c_kirk,journer_of_truth,juno_macguff,killa_kara,king_in_yellow,king_luther,lass_doug,leia_it_ontheline,leon,lion_eyes,lizzie_regna,lt_col_j_shep,lt_col_j_shepp,luke_5kywalker,m_ali,m_c_fly,m_clarke_dunk,m_poppins,madthugpug,marc_garv,mary_shell,med_evarz,med_evzrz,mh_hamilton,mjay_m_walker,muld0r,neoone,oz,pick4rluc,poitier_27,pugluv4vr,purple1,q_bey,r0bertm4rley,rain3y,raygun_chandler,renaldos_malc,revolution808,rey_tr4cer,ripley_or_not,rob_rob_taylor,robo_deckard,rocky_b,runningman23,sam_cart,sammy_l_jack,scook,seria_mau_g,seven_out_of_9,shareef_j,shawn_aa,sidney_prescott,sp0ck_08,sportsfan2031,tam_riv,tchalla,terrance_cruz,thadd_0s,thedude,theformalartist,thegreat,thegreatvandross,thepowerful,theshrillery,troy_cole,turn_a_nat,turner_t,uhur4,universe,wc_handy,whois_hermano,wiley_curry,will_de_vaughn,wonderous_steve,x_mal,youngtwokay,yung_lespaul,zap_dweezil,zap_franscisco,zap_moon,zoe_wash".split(","); | |
| let profiles = "empl_pages,profiles,my_account,my_login,profile,public_profiles,mypassport,p33ps".split(",") | |
| let controls = "cpanel,c_panel,userpanel,user_panel,myaccount,my_account,mypanel,my_panel,mylogin,my_login,user_backend,upanel,u_panel,__av93zk9b9,mypassport".split(",") | |
| let bots = "helperbot,libbot,helpbot,reqbot,adminbot,csrbot,dsearcher,datasearcher,querybot,custbot,clarence,kb_bot,knowledgebase,knowdb,clerkbot".split(",") // ,knowdb?? | |
| const resetCommands = "clear_pass,pass_reset,resetpass,show_pass,reset_password,renewpass,renew_pass,passwordreset".split(","); | |
| let target = null | |
| if (args.t) { | |
| target = args.t | |
| } | |
| let npcs = "abandoned,abndnd,anon,anonymous,derelict,uknown,unidentified,unknown".split(",") // known npc handles | |
| let rating_short = "_jr,_dd,_wb,_pr,_ls".split(","), | |
| rating_long = "`0junk`,`1deck`,`2wrck`,`3phrk`,`4leet`".split(",") | |
| let class_short = "wvr_,ttl_,wlf_,rvn_,stg_".split(","), | |
| class_long = "`Narch`,`Olock`,`Pinfl`,`Qscav`,`Sexec`".split(",") | |
| let rst = "????", | |
| rst2 = "", | |
| debug = "" | |
| // handle no args | |
| if (args == null || (args && typeof args === 'object' && !Object.keys(args).length)) | |
| return { ok: false, msg: "\nUsage: aperture.t1 { t:#s.corp.public } " } | |
| let t = args.t, | |
| ok = true | |
| if (args.blog) { | |
| return decorrupt({navigation:"blog"}) | |
| } | |
| // handle non fullsec targets | |
| let get_level = #fs.scripts.get_level({ name: t.name }) | |
| if (get_level < 4) | |
| return { ok: false, msg: "`XInsecure Script`" } | |
| // ERROR CHECKING DONE | |
| let msg = "\n`HAPERTURE SCIENCE :: TIER 1`\n\n" | |
| let stage = 1 | |
| let r = "", | |
| pages = "", | |
| commands = "", | |
| directory = "", | |
| password = "", | |
| panel = "" | |
| r = target.call() | |
| if (r && r.msg && r.msg.includes("Shift operation")) | |
| return msg + "Shift Operation in Progress. Please choose another Corp" | |
| // get both pages keyword | |
| r = decorrupt(); | |
| pages = r.match(/(\w+) \| (\w+)/) | |
| // get command keyword | |
| r = decorrupt({}) | |
| commands = r.match(/ith (\w+):"(\w+)"$/) | |
| directory = commands[2] | |
| let command = commands[1], | |
| userCommand = "", | |
| passCommand = "", | |
| resetBot = "", | |
| resetCommand = "", | |
| resetPassword = "" | |
| // parse error, stop now | |
| if (pages & commands === false) | |
| return { ok: false, msg: msg } | |
| // get password | |
| let o = {}; | |
| o[commands[1]] = pages[2]; | |
| r = decorrupt(o); | |
| password = r.match(/tegy (\w+)/); | |
| if (password === null) | |
| return { ok: false, msg: msg } | |
| // get password key name | |
| let variants = ["p", "pass", "password"] | |
| let passwordVariant = "" | |
| for (var v in variants) { | |
| o[commands[1]] = commands[2] | |
| o[variants[v]] = password[1] | |
| r = t.call(o) | |
| if (r.indexOf('Authenticated') > -1) { | |
| passwordVariant = variants[v] | |
| break | |
| } | |
| } | |
| // get projects | |
| o[commands[1]] = pages[1] | |
| r = decorrupt(o) // {command:projects} | |
| let pm = "" | |
| let um = "" | |
| const findMatch = (largeString, smallStrings) => { | |
| return smallStrings.find(smallString => largeString.includes(smallString)); | |
| }; | |
| const profileString = findMatch(r, profiles); | |
| // split the blog page into lines | |
| let rows = r.split("\n") | |
| // sets to store only unique values | |
| let p2 = new Set() // projects | |
| let u3 = new Set() // usernames | |
| // for each even line (skip odds which are timestamps) | |
| for (let i = 1; i < rows.length; i += 2) { | |
| let line = rows[i] | |
| // get projects | |
| for (let c in projs) { | |
| let cc = projs[c] | |
| if (line.includes(cc)) { | |
| p2.add(cc) | |
| } | |
| } | |
| // get users | |
| for (let un in users) { | |
| let user = users[un] | |
| if (line.includes(user)) { | |
| u3.add(user) | |
| } | |
| } | |
| } | |
| let loc_set = new Set() | |
| // NPC LOCATIONS | |
| let u2 = new Set() | |
| p2.forEach(function (project_name) { | |
| o[commands[1]] = commands[2] // e.g. open:employees | |
| o['project'] = project_name; | |
| let vx = decorrupt(o, 700).split("\n") | |
| // 10 | |
| let c = 0 | |
| for (var fs in vx) { | |
| let loc = vx[fs] | |
| let m5 = loc.match(/^([\w]+\.[\w]+)$/) | |
| if (m5) { | |
| u2.add(loc) | |
| // is_npc(loc) ? insertNPC(loc) : insertPlayer(loc); | |
| let rating = get_rating(loc) | |
| let _class = get_class(loc) | |
| if (!rating.includes("plyr")) { | |
| loc_set.add({ loc, rtng: rating, clss: _class }) | |
| insertNPC(loc) | |
| } | |
| else | |
| { | |
| insertPlayer(loc) | |
| } | |
| // um = um + " " + loc.padEnd(48," ") + rating + _class + "\n" | |
| c++ | |
| } | |
| } | |
| }) | |
| let actualPassword = password[1] | |
| let usrcnt = 0 | |
| let panelCount = 0; | |
| // if (args.cpanel) { | |
| let panelUserList = []; | |
| // GET CONTROL PANEL KEYWORD & USERNAME KEYWORD | |
| for (let i = 0; i < controls.length; i++) { | |
| let args = {} | |
| args[command] = controls[i] | |
| r = decorrupt(args); | |
| if (r.includes(controls[i])) { | |
| userCommand = r.split(" ")[0] | |
| panel = controls[i] | |
| break; | |
| } | |
| } | |
| // GET PASSWORD KEYWORD & USER LIST | |
| if (panel.length > 0) { | |
| for (let i = 0; i < users.length; i++) { | |
| let args = {} | |
| args[command] = panel; | |
| args[userCommand] = users[i]; | |
| r = decorrupt(args); | |
| if (r.includes('incorrect')) { | |
| if (passCommand = "") | |
| passCommand = r.split(" ")[1] // second word | |
| else | |
| passCommand = 'pass' | |
| panelUserList.push(users[i]) | |
| } | |
| if (checkTimeout()) break; | |
| } | |
| } | |
| //debug += `${command}:"${panel}" ${userCommand}:"${panelUserList[0]}" ${passCommand}\n`; | |
| //debug += `${panelUserList.length} users found with control panel access\n` | |
| const regexReset = /SPECIFY\s+(\w+)/; | |
| const regexPassword = /RESET TO\s+(\w+)/; | |
| // if we found users | |
| // if (panelUserList.length > 0) { | |
| for (let iu = 0; iu < panelUserList.length; iu++) { | |
| let currentUser = panelUserList[iu]; | |
| // loop through the list of bot names | |
| if (resetBot == "") | |
| for (let i = 0; i < bots.length; i++) { | |
| let args = {} | |
| args[command] = panel; | |
| args[userCommand] = currentUser; // panelUserList[0]; | |
| // try reset command (consistent) | |
| args[bots[i]] = "reset"; | |
| // get response sans-color (the keyword after SPECIFY is colour coded) | |
| r = decolor(decorrupt(args)); | |
| const foundCommand = resetCommands.find(command => r.includes(command)); | |
| if (foundCommand) { | |
| resetBot = bots[i]; | |
| args[resetBot] = foundCommand; | |
| resetCommand = foundCommand; | |
| r = decolor(decorrupt(args)); | |
| } | |
| let matches = r.match(regexReset); | |
| if (matches) { | |
| resetBot = bots[i]; | |
| resetCommand = matches[1]; | |
| //debug += `Reset Bot: ${resetBot}\nReset Command: ${resetCommand}\n` | |
| break; | |
| } | |
| // debug += r | |
| r = null; | |
| } | |
| if (resetBot && resetCommand) { | |
| let args = {} | |
| args[command] = panel; | |
| args[userCommand] = currentUser; // panelUserList[0]; | |
| args[resetBot] = resetCommand; | |
| r = decolor(decorrupt(args)); | |
| const matches = r.match(regexPassword); | |
| if (matches) { | |
| r = null; | |
| resetPassword = matches[1]; | |
| delete args[resetBot] | |
| args[passCommand] = resetPassword; | |
| args.PANELOPT = 'recent'; | |
| r = target.call(args) | |
| if (Array.isArray(r)) { | |
| for (let il = 0; il < r.length; il++) { | |
| let loc = r[il] | |
| panelCount++; | |
| loc_set.add({ loc, rtng: get_rating(loc), clss: get_class(loc) }) | |
| is_npc(loc) ? insertNPC(loc) : insertPlayer(loc); | |
| } | |
| } | |
| } | |
| } else { | |
| //debug += `Reset Bot: ${resetBot}\nReset Command: ${resetCommand}\n` | |
| } | |
| if (checkTimeout) break; | |
| } | |
| // Convert the Set to an Array for sorting | |
| let arrayData = Array.from(loc_set); | |
| // Sort the Array | |
| arrayData.sort((a, b) => { | |
| if (a.rtng < b.rtng) return -1; | |
| if (a.rtng > b.rtng) return 1; | |
| if (a.clss < b.clss) return -1; | |
| if (a.clss > b.clss) return 1; | |
| if (a.loc < b.loc) return -1; | |
| if (a.loc > b.loc) return 1; | |
| return 0; | |
| }); | |
| loc_set = new Set(arrayData); | |
| let et = Date.now() - _START | |
| if (args.portal) | |
| return `[!] ${loc_set.size}` | |
| // add locs to output | |
| msg += `\nFound ${loc_set.size} NPCs from ${p2.size} projects ` | |
| if (usrcnt > 0) msg += `and ${usrcnt} profiles ` | |
| if (panelCount > 0) msg += `and ${panelUserList.length} control panels ` | |
| msg += `in ${et}ms\n\n` | |
| if (!args.quiet) | |
| msg += convertSetToJsonTable(loc_set) + "\n\n" | |
| if (args.projects) { | |
| debug += "Projects:\n" | |
| p2.forEach((project_name) => { | |
| debug += "- " + project_name + "\n" | |
| }); | |
| } | |
| if (context.caller == 'aperture') msg += debug | |
| return msg; | |
| // ------------------------------------------------------------------------------------------ | |
| function checkTimeout(x = 4500) { | |
| return (Date.now() - _START) > x; | |
| } | |
| function convertSetToJsonTable(set) { | |
| if (set.size === 0) return "No data available"; | |
| // Initialize headers and column width trackers | |
| let headers = []; | |
| let columnWidths = {}; | |
| // First, determine headers and initialize widths by examining the first object in the set | |
| set.forEach(item => { | |
| headers = Object.keys(item); | |
| headers.forEach(header => { | |
| let l = header.length | |
| let i = ("" + (decolor(item[header]) || '')) | |
| columnWidths[header] = Math.max(l, i.length) | |
| }); | |
| return true; // Exit after processing the first item | |
| }); | |
| // Update columnWidths based on all data in the set | |
| set.forEach(item => { | |
| headers.forEach(header => { | |
| const dataLength = ("" + decolor(item[header] || '')).length; | |
| if (dataLength > columnWidths[header]) { | |
| columnWidths[header] = dataLength; | |
| } | |
| }); | |
| }); | |
| // ━━━━━━━━━╋ | |
| // Create header row | |
| let headerRow = headers.map(header => ("`1" + header.padEnd(columnWidths[header])).toUpperCase() + "`").join(' ┃ ') | |
| let rows = [headerRow]; | |
| // Separator row | |
| let separatorRow = headers.map(header => '━'.repeat(columnWidths[header])).join('━━╋━━'); | |
| rows.push(separatorRow); | |
| // Data rows | |
| set.forEach(item => { | |
| let row = headers.map(header => ("" + (item[header] || '')).padEnd(columnWidths[header])).join(' ┃ '); | |
| rows.push(row); | |
| }); | |
| // Join all rows into a single string with new lines | |
| return rows.join('\n'); | |
| } | |
| function decolor(val) { | |
| return val.replaceAll(/`\w(.*?)`/g, '$1') | |
| } | |
| // check if npc from handle | |
| function is_npc(handle) { | |
| for (var ih = 0; ih < npcs.length; ih++) { | |
| if (handle.includes(npcs[ih])) { | |
| return true | |
| } | |
| } | |
| return false | |
| } | |
| // get lock level rating | |
| function get_rating(loc) { | |
| let result = "none" | |
| for (let i = 0; i < 5; i++) { | |
| let r = rating_short[i] | |
| let sp = loc.split(".")[0] | |
| if (!is_npc(sp)) { | |
| result = "`5plyr`" | |
| break | |
| } else if (sp.includes(r)) { | |
| result = rating_long[i]; | |
| break | |
| } | |
| } | |
| return result // .padEnd(20," ") | |
| } | |
| // get class/loot rating | |
| function get_class(um) { | |
| rst2 = "none" | |
| for (let x = 0; x < 5; x++) { | |
| let r = class_short[x] | |
| let sp = um.split(".")[0] | |
| if (!sp.includes("_")) { | |
| rst2 = "" | |
| break | |
| } else | |
| if (sp.includes(r)) { | |
| rst2 = class_long[x] | |
| break | |
| } | |
| } | |
| return rst2 // .padEnd(16," ") | |
| } | |
| // decorrupt text | |
| function decorrupt(a) { | |
| let r = new RegExp(`[¡¢Á¤Ã¦§¨©ª]`), | |
| s = /`\w(.)`/g, | |
| x = (a) ? JSON.parse(JSON.stringify(a)) : null, | |
| d = _ => ([].concat(t.call(x))).join("\n").toString().replace(s, "$1").split(""), | |
| o = d() | |
| while (r.test(o.join(""))) | |
| d().forEach((p, i) => { | |
| if (r.test(o[i])) | |
| o[i] = p | |
| }) | |
| return o.join("") | |
| } | |
| function insertNPC(location) { | |
| // const tier = #fs.scripts.get_level({ name: location }) | |
| const timestamp = Date.now() | |
| const query = { tier:1, location }; | |
| const update = { $set: { timestamp,source:'aperture.t1' } }; | |
| try { | |
| #db.us( | |
| query, | |
| update //, { upsert: true } | |
| ); | |
| } catch (e) { } | |
| } | |
| function insertPlayer(pvpLocation) { | |
| let level = String(#fs.scripts.get_level({name:pvpLocation})) | |
| if (!isNumeric(level)) return false; | |
| const pvpUsername = pvpLocation.split(".")[0] | |
| const query = { group: "pvp", pvpUsername }; | |
| const update = { $set: { pvpLocation,source:'aperture.t1' } }; | |
| try { | |
| #db.us( | |
| query, | |
| update | |
| ); | |
| } catch (e) {} | |
| } | |
| function isNumeric(str) { | |
| if (typeof str != "string") return false // we only process strings! | |
| return !isNaN(str) && // use type coercion to parse the _entirety_ of the string (`parseFloat` alone does not do this)... | |
| !isNaN(parseFloat(str)) // ...and ensure strings of whitespace fail | |
| } | |
| function printColumns(arr, width) { | |
| const spacing = 6; // fixed spacing between columns | |
| let maxStrLength = 0; | |
| let output = "" | |
| // Calculate the maximum string length | |
| for (let i = 0; i < arr.length; i++) { | |
| if (arr[i].length > maxStrLength) { | |
| maxStrLength = arr[i].length; | |
| } | |
| } | |
| const colWidth = maxStrLength + spacing; // width of each column including spacing | |
| const numCols = Math.floor(width / colWidth); // number of columns that fit in the given width | |
| const numRows = Math.ceil(arr.length / numCols); // number of rows needed | |
| for (let row = 0; row < numRows; row++) { | |
| let rowStr = ''; | |
| for (let col = 0; col < numCols; col++) { | |
| const index = row + col * numRows; | |
| if (index < arr.length) { | |
| rowStr += arr[index].padEnd(colWidth, ' '); | |
| } | |
| } | |
| output += (rowStr) + "\n"; | |
| } | |
| return output | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment