intel-screenbot

An Ingress Intel Map Bot for Hangoutsbot
git clone git://archive.git.mtrnord.blog/MTRNord/intel-screenbot.git
Log | Files | Refs | README | LICENSE

commit f8d66db0334be3ff92e0c9af4c0e027b6df52dd4
parent 663f60d1aeacd193d22116608f57001e0096e3b9
Author: Marcel <MTRNord@users.noreply.github.com>
Date:   Mon,  6 Mar 2017 20:00:51 +0100

Merge pull request #7 from MTRNord/PortalInfo

Add Portal info Commands
Diffstat:
MREADME.md | 18++++++++++++------
M__init__.py | 172+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
Mscreencap.js | 266+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
3 files changed, 385 insertions(+), 71 deletions(-)

diff --git a/README.md b/README.md @@ -19,10 +19,10 @@ To install the plugin you need to: ## Configuration with Email Password -**IMPORTANT: DO NOT USE YOUR MAIN ACCOUNT! I AM NOT RESPONSIBLE IF YOU ACCOUNT GETS BANNED! USE AT YOUR OWN RISK** +**IMPORTANT: DO NOT USE YOUR MAIN ACCOUNT! I AM NOT RESPONSIBLE IF YOUR ACCOUNT GETS BANNED! USE AT YOUR OWN RISK** -*Note DON'T set cookies up when using emil/password* -For using the Intel Screenbot you need to add the following to the config.json: +*Note: DON'T set cookies up when using email/password*<br \><br \> +For using the Intel Screenbot you need to add the following json-code to the config.json: ``` "intel_screenbot": { @@ -34,8 +34,8 @@ For using the Intel Screenbot you need to add the following to the config.json: } ``` -According to the official INSTALL Documention of the hangoutbot you will find the config.json in `/<username>/.local/share/hangupsbot/` -(NOTE! add an comma behind the last element of the config.json and add it befor the outer element closes) +According to the official INSTALL Documention of the hangoutbot you will find the config.json in `/<username>/.local/share/hangupsbot/` <br \> +(NOTE! add an comma behind the last element of the config.json and add it before the outer element closes) Also you need to add `intel_screenbot` to the plugins. @@ -86,9 +86,15 @@ Also you need to add `intel_screenbot` to the plugins. * If no `<url>` is supplied, use the default screenshot URL (or reply with an error if no URL is set) * `z=` lets you change the zoomlevel of the map +`/portalpic <url>` +* Makes a screenshot of the Portalinfo of the defined portal. + +`/portalinfo <url>` +* Gives you a text version of the most important Portal Information. (Pretty long!) + ## PhantomJS Installation -Only tested: +Only tested way to install: ``` wget https://cnpmjs.org/downloads/phantomjs-2.1.1-linux-x86_64.tar.bz2 diff --git a/__init__.py b/__init__.py @@ -9,14 +9,21 @@ logger = logging.getLogger(__name__) def _initialise(bot): - plugins.register_user_command(["intel", "iitc", "active_iitcplugins"]) + plugins.register_user_command(["intel", "iitc", "portalpic", "portalinfo", "active_iitcplugins"]) plugins.register_admin_command(["setintel", "show_iitcplugins", "set_iitcplugins"]) _get_iitc_plugins(bot) @asyncio.coroutine -def _open_file(name): - return open(name, 'rb') +def _open_file(name, otype): + return open(name, otype) + +@asyncio.coroutine +def readline(f): + while True: + data = f.readline() + if data: + return data def _parse_onlineRepos(url, ext=''): page = requests.get(url).text @@ -78,7 +85,7 @@ def _get_lines(shell_command): return p.returncode, output, True @asyncio.coroutine -def _screencap(url, args_filepath, filepath, filename, bot, event): +def _screencap(url, args_filepath, filepath, filename, bot, event, arguments): os.chmod(filepath, 0o666) loop = asyncio.get_event_loop() command = 'phantomjs hangupsbot/plugins/intel_screenbot/screencap.js "' + args_filepath + '"' @@ -88,22 +95,30 @@ def _screencap(url, args_filepath, filepath, filename, bot, event): # read the resulting file into a byte array # yield from asyncio.sleep(10) - file_resource = yield from _open_file(filepath) - file_data = yield from loop.run_in_executor(None, file_resource.read) - image_data = yield from loop.run_in_executor(None, io.BytesIO, file_data) - if status: - try: - image_id = yield from bot._client.upload_image(image_data, filename=filename) - yield from bot.coro_send_message(event.conv.id_, None, image_id=image_id) - os.unlink(filepath) - os.unlink(args_filepath) - except Exception as e: + if (arguments['screenshotfunction'] != 'portalinfoText'): + file_resource = yield from _open_file(filepath, 'rb') + file_data = yield from loop.run_in_executor(None, file_resource.read) + image_data = yield from loop.run_in_executor(None, io.BytesIO, file_data) + if status: + try: + image_id = yield from bot._client.upload_image(image_data, filename=filename) + yield from bot.coro_send_message(event.conv.id_, None, image_id=image_id) + os.unlink(filepath) + os.unlink(args_filepath) + except Exception as e: + os.unlink(filepath) + os.unlink(args_filepath) + logger.exception("upload failed: {}".format(url)) + logger.exception("exception: {}".format(e)) + yield from bot.coro_send_message(event.conv_id, "<i>error uploading screenshot</i>") + else: + if status: + response_file = yield from _open_file(arguments['portalinfoResponse'], 'r') + response = yield from readline(response_file) + yield from bot.coro_send_message(event.conv.id_, response.replace("'", "")) os.unlink(filepath) os.unlink(args_filepath) - logger.exception("upload failed: {}".format(url)) - logger.exception("exception: {}".format(e)) - yield from bot.coro_send_message(event.conv_id, "<i>error uploading screenshot</i>") - + os.unlink(arguments['portalinfoResponse']) def setintel(bot, event, *args): """set url for current converation for the intel or iitc command. @@ -121,7 +136,122 @@ def setintel(bot, event, *args): html = "<i><b>{}</b> updated screenshot URL".format(event.user.full_name) yield from bot.coro_send_message(event.conv, html) +def portalpic(bot, event, *args): + """get a screenshot of the portalInfo by URL.""" + + arguments = {} + if args: + if len(args) > 1: + url = ' '.join(str(i) for i in args) + else: + url = args[0] + if '"' in url: + url = url.replace('"', '') + else: + html = "<i><b>{}</b> No Arguments provided".format(event.user.full_name) + yield from bot.coro_send_message(event.conv, html) + + if bot.config.exists(["intel_screenbot", "email"]): + if bot.config.exists(["intel_screenbot", "password"]): + email = bot.config.get_by_path(["intel_screenbot", "email"]) + password = bot.config.get_by_path(["intel_screenbot", "password"]) + arguments['email'] = email + arguments['password'] = password + else: + html = "<i><b>{}</b> No Intel password has been added to config. Unable to authenticate".format(event.user.full_name) + yield from bot.coro_send_message(event.conv, html) + else: + html = "<i><b>{}</b> No Intel Email/password has been added to config. Unable to authenticate".format(event.user.full_name) + yield from bot.coro_send_message(event.conv, html) + + if url is None: + html = "<i><b>{}</b> No Portal URL has been set for screenshots.".format(event.user.full_name) + yield from bot.coro_send_message(event.conv, html) + else: + if re.match(r'(http(s)?:\/\/)', url): + yield from bot.coro_send_message(event.conv_id, "<i>Portal Info requested, please wait...</i>") + filepath = tempfile.NamedTemporaryFile(suffix=".png", delete=False).name + filename = filepath.split('/', filepath.count('/'))[-1] + args_filepath = tempfile.NamedTemporaryFile(prefix="args_{}".format(event.conv_id), suffix=".json", delete=False).name + + arguments['url'] = url + arguments['filepath'] = filepath + arguments['screenshotfunction'] = "portalinfoScreen" + + with open(args_filepath, 'w') as out: + out.write(json.dumps(arguments)) + + try: + loop = asyncio.get_event_loop() + image_data = yield from _screencap(url, args_filepath, filepath, filename, bot, event) + except Exception as e: + yield from bot.coro_send_message(event.conv_id, "<i>error getting screenshot</i>") + logger.exception("screencap failed".format(url)) + return + else: + html = "<i><b>{}</b> No URL found in Arguments".format(event.user.full_name) + yield from bot.coro_send_message(event.conv, html) + +def portalinfo(bot, event, *args): + """get a of the portalInfo by URL.""" + + arguments = {} + + if args: + if len(args) > 1: + url = ' '.join(str(i) for i in args) + else: + url = args[0] + if '"' in url: + url = url.replace('"', '') + else: + html = "<i><b>{}</b> No Arguments provided".format(event.user.full_name) + yield from bot.coro_send_message(event.conv, html) + + if bot.config.exists(["intel_screenbot", "email"]): + if bot.config.exists(["intel_screenbot", "password"]): + email = bot.config.get_by_path(["intel_screenbot", "email"]) + password = bot.config.get_by_path(["intel_screenbot", "password"]) + arguments['email'] = email + arguments['password'] = password + else: + html = "<i><b>{}</b> No Intel password has been added to config. Unable to authenticate".format(event.user.full_name) + yield from bot.coro_send_message(event.conv, html) + else: + html = "<i><b>{}</b> No Intel Email/password has been added to config. Unable to authenticate".format(event.user.full_name) + yield from bot.coro_send_message(event.conv, html) + + if url is None: + html = "<i><b>{}</b> No Portal URL has been set for portal Info.".format(event.user.full_name) + yield from bot.coro_send_message(event.conv, html) + else: + if re.match(r'(http(s)?:\/\/)', url): + yield from bot.coro_send_message(event.conv_id, "<i>Portal Info requested, please wait...</i>") + filepath = tempfile.NamedTemporaryFile(suffix=".png", delete=False).name + portalinfoResponse = tempfile.NamedTemporaryFile(prefix="response_{}".format(event.conv_id), delete=False).name + filename = filepath.split('/', filepath.count('/'))[-1] + args_filepath = tempfile.NamedTemporaryFile(prefix="args_{}".format(event.conv_id), suffix=".json", delete=False).name + + arguments['url'] = url + arguments['filepath'] = filepath + arguments['screenshotfunction'] = "portalinfoText" + arguments['portalinfoResponse'] = portalinfoResponse + + with open(args_filepath, 'w') as out: + out.write(json.dumps(arguments)) + + try: + loop = asyncio.get_event_loop() + image_data = yield from _screencap(url, args_filepath, filepath, filename, bot, event, arguments) + except Exception as e: + yield from bot.coro_send_message(event.conv_id, "<i>error getting screenshot</i>") + logger.exception("screencap failed".format(url)) + return + else: + html = "<i><b>{}</b> No URL found in Arguments".format(event.user.full_name) + yield from bot.coro_send_message(event.conv, html) + def intel(bot, event, *args): """get a screenshot of a search term or intel URL or the default intel URL of the hangout.""" @@ -195,13 +325,14 @@ def intel(bot, event, *args): arguments['url'] = url arguments['filepath'] = filepath arguments['maptype'] = "intel" + arguments['screenshotfunction'] = "map" with open(args_filepath, 'w') as out: out.write(json.dumps(arguments)) try: loop = asyncio.get_event_loop() - image_data = yield from _screencap(url, args_filepath, filepath, filename, bot, event) + image_data = yield from _screencap(url, args_filepath, filepath, filename, bot, event, arguments) except Exception as e: yield from bot.coro_send_message(event.conv_id, "<i>error getting screenshot</i>") logger.exception("screencap failed".format(url)) @@ -291,13 +422,14 @@ def iitc(bot, event, *args): arguments['url'] = url arguments['filepath'] = filepath arguments['maptype'] = "iitc" + arguments['screenshotfunction'] = "map" with open(args_filepath, 'w') as out: out.write(json.dumps(arguments)) try: loop = asyncio.get_event_loop() - image_data = yield from _screencap(url, args_filepath, filepath, filename, bot, event) + image_data = yield from _screencap(url, args_filepath, filepath, filename, bot, event, arguments) except Exception as e: yield from bot.coro_send_message(event.conv_id, "<i>error getting screenshot</i>") logger.exception("screencap failed".format(url)) diff --git a/screencap.js b/screencap.js @@ -22,6 +22,10 @@ if (args.length === 1) { var filepath = arguments['filepath'] var user = arguments['email'] var pass = arguments['password'] + var screenshotfunction = arguments['screenshotfunction'] + if(screenshotfunction == "portalinfoText"){ + var portalinfoResponse = arguments['portalinfoResponse'] + } } function loadCookies(callback) { @@ -171,11 +175,220 @@ function login(l, p, url) { }); } +function map(search){ + setTimeout(function() { + if (search != 'nix') { + searchfunc(search); + } + waitFor({ + timeout: 240000, + check: function () { + return page.evaluate(function(zoomlevel) { + if (document.querySelector('.map').textContent.indexOf('done') != -1) { + return true; + }else{ + console.log('generateFakeOutput') + return false; + } + }, zoomlevel); + }, + success: function () { + var startTime = new Date().getTime(); + var interval = setInterval(function(){ + if(new Date().getTime() - startTime > 5000){ + hideDebris(); + prepare('1280', '720'); + main(); + clearInterval(interval); + return; + } + console.log('generateFakeOutput') + }, 1000); + }, + error: function () { + var startTime = new Date().getTime(); + var interval = setInterval(function(){ + if(new Date().getTime() - startTime > 5000){ + hideDebris(); + prepare('1280', '720'); + main(); + clearInterval(interval); + return; + } + console.log('generateFakeOutput') + }, 1000); + } + }); + }, "1000"); +} + +function portalinfoScreen(){ + setTimeout(function() { + waitFor({ + timeout: 240000, + check: function () { + return page.evaluate(function() { + if (document.querySelector('.map').textContent.indexOf('done') != -1) { + return true; + }else{ + console.log('generateFakeOutput') + return false; + } + }); + }, + success: function () { + var clipRect = page.evaluate(function(){ + return document.querySelector('#sidebar').getBoundingClientRect(); + }); + page.evaluate(function(){ + document.querySelector('#playerstat').style.display = 'none'; + document.querySelector('#searchwrapper').style.display = 'none'; + document.querySelector('#redeem').style.display = 'none'; + }); + setTimeout(function() { + var elementHeight = page.evaluate(function(){ + return $("#sidebar").height(); + }); + + page.clipRect = { + top: clipRect.top, + left: clipRect.left, + width: clipRect.width, + height: elementHeight + } + setTimeout(function() {s(filepath)}, "1000"); + }, "2000"); + }, + error: function () { + var clipRect = page.evaluate(function(){ + return document.querySelector('#sidebar').getBoundingClientRect(); + }); + + setTimeout(function() { + var elementHeight = page.evaluate(function(){ + return $("#sidebar").height(); + }); + + page.clipRect = { + top: clipRect.top, + left: clipRect.left, + width: clipRect.width, + height: elementHeight + } + setTimeout(function() {s(filepath)}, "1000"); + }, "2000"); + } + }); + }, "1000"); +} + +function portalinfoText(){ + setTimeout(function() { + waitFor({ + timeout: 240000, + check: function () { + return page.evaluate(function() { + if ((document.querySelector('.map').textContent.indexOf('done') != -1) || (document.getElementById("resodetails").rows[0])) { + return true; + }else{ + console.log('generateFakeOutput') + return false; + } + }); + }, + success: function () { + var PortalName = page.evaluate(function(){ + return document.getElementById("portaldetails").getElementsByClassName("title")[0].innerHTML; + }); + var reso1 = page.evaluate(function(){ + return document.getElementById("resodetails").rows[0].cells[1].firstElementChild.getAttribute("title"); + }); + var reso2 = page.evaluate(function(){ + return document.getElementById("resodetails").rows[0].cells[2].firstElementChild.getAttribute("title"); + }); + var reso3 = page.evaluate(function(){ + return document.getElementById("resodetails").rows[1].cells[1].firstElementChild.getAttribute("title"); + }); + var reso4 = page.evaluate(function(){ + return document.getElementById("resodetails").rows[1].cells[2].firstElementChild.getAttribute("title"); + }); + var reso5 = page.evaluate(function(){ + return document.getElementById("resodetails").rows[2].cells[1].firstElementChild.getAttribute("title"); + }); + var reso6 = page.evaluate(function(){ + return document.getElementById("resodetails").rows[2].cells[2].firstElementChild.getAttribute("title"); + }); + var reso7 = page.evaluate(function(){ + return document.getElementById("resodetails").rows[3].cells[1].firstElementChild.getAttribute("title"); + }); + var reso8 = page.evaluate(function(){ + return document.getElementById("resodetails").rows[3].cells[2].firstElementChild.getAttribute("title"); + }); + var text = PortalName.replace(/(?:\r\n|\r|\n)/g, '<br />').replace(/(?:\t)/g, ' ') + "<br /><br /><b>Resonator 1:</b><br />" + reso1.replace(/(?:\r\n|\r|\n)/g, '<br />').replace(/(?:\t)/g, ' ') + "<br /><b>Resonator 2:</b><br />" + reso2.replace(/(?:\r\n|\r|\n)/g, '<br />').replace(/(?:\t)/g, ' ') + "<br /><b>Resonator 3:</b><br />" + reso3.replace(/(?:\r\n|\r|\n)/g, '<br />').replace(/(?:\t)/g, ' ') + "<br /><b>Resonator 4:</b><br />" + reso4.replace(/(?:\r\n|\r|\n)/g, '<br />').replace(/(?:\t)/g, ' ') + "<br /><b>Resonator 5:</b><br />" + reso5.replace(/(?:\r\n|\r|\n)/g, '<br />').replace(/(?:\t)/g, ' ') + "<br /><b>Resonator 6:</b><br />" + reso6.replace(/(?:\r\n|\r|\n)/g, '<br />').replace(/(?:\t)/g, ' ') + "<br /><b>Resonator 7:</b><br />" + reso7.replace(/(?:\r\n|\r|\n)/g, '<br />').replace(/(?:\t)/g, ' ') + "<br /><b>Resonator 8:</b><br />" + reso8.replace(/(?:\r\n|\r|\n)/g, '<br />').replace(/(?:\t)/g, ' ') + console.log(text) + fs.write(portalinfoResponse, text, 'w'); + var startTime = new Date().getTime(); + var startTime = new Date().getTime(); + var interval = setInterval(function(){ + if(new Date().getTime() - startTime > 5000){ + clearInterval(interval); + phantom.exit(0); + return; + } + console.log('doSomeOutput') + }, 1000); + }, + error: function () { + var PortalName = page.evaluate(function(){ + return document.getElementById("portaldetails").getElementsByClassName("title")[0].innerHTML; + }); + var reso1 = page.evaluate(function(){ + return document.getElementById("resodetails").rows[0].cells[1].firstElementChild.getAttribute("title"); + }); + var reso2 = page.evaluate(function(){ + return document.getElementById("resodetails").rows[0].cells[2].firstElementChild.getAttribute("title"); + }); + var reso3 = page.evaluate(function(){ + return document.getElementById("resodetails").rows[1].cells[1].firstElementChild.getAttribute("title"); + }); + var reso4 = page.evaluate(function(){ + return document.getElementById("resodetails").rows[1].cells[2].firstElementChild.getAttribute("title"); + }); + var reso5 = page.evaluate(function(){ + return document.getElementById("resodetails").rows[2].cells[1].firstElementChild.getAttribute("title"); + }); + var reso6 = page.evaluate(function(){ + return document.getElementById("resodetails").rows[2].cells[2].firstElementChild.getAttribute("title"); + }); + var reso7 = page.evaluate(function(){ + return document.getElementById("resodetails").rows[3].cells[1].firstElementChild.getAttribute("title"); + }); + var reso8 = page.evaluate(function(){ + return document.getElementById("resodetails").rows[3].cells[2].firstElementChild.getAttribute("title"); + }); + var text = PortalName.replace(/(?:\r\n|\r|\n)/g, '<br />').replace(/(?:\t)/g, ' ') + "<br /><br /><b>Resonator 1:</b><br />" + reso1.replace(/(?:\r\n|\r|\n)/g, '<br />').replace(/(?:\t)/g, ' ') + "<br /><b>Resonator 2:</b><br />" + reso2.replace(/(?:\r\n|\r|\n)/g, '<br />').replace(/(?:\t)/g, ' ') + "<br /><b>Resonator 3:</b><br />" + reso3.replace(/(?:\r\n|\r|\n)/g, '<br />').replace(/(?:\t)/g, ' ') + "<br /><b>Resonator 4:</b><br />" + reso4.replace(/(?:\r\n|\r|\n)/g, '<br />').replace(/(?:\t)/g, ' ') + "<br /><b>Resonator 5:</b><br />" + reso5.replace(/(?:\r\n|\r|\n)/g, '<br />').replace(/(?:\t)/g, ' ') + "<br /><b>Resonator 6:</b><br />" + reso6.replace(/(?:\r\n|\r|\n)/g, '<br />').replace(/(?:\t)/g, ' ') + "<br /><b>Resonator 7:</b><br />" + reso7.replace(/(?:\r\n|\r|\n)/g, '<br />').replace(/(?:\t)/g, ' ') + "<br /><b>Resonator 8:</b><br />" + reso8.replace(/(?:\r\n|\r|\n)/g, '<br />').replace(/(?:\t)/g, ' ') + console.log(text) + fs.write(portalinfoResponse, text.replace(/'/g, ''), 'w'); + var startTime = new Date().getTime(); + var startTime = new Date().getTime(); + var interval = setInterval(function(){ + if(new Date().getTime() - startTime > 5000){ + clearInterval(interval); + phantom.exit(0); + return; + } + console.log('doSomeOutput') + }, 1000); + } + }); + }, "1000"); +} + function afterLogin(url, search, mode) { page.viewportSize = { width: '1280', height: '720' }; page.open(url, function(status) { console.log(url) - if (status !== 'success') {console.log('unable to connect to remote server afterPlainLogin'); phantom.exit(0);} + if (status !== 'success') {console.log('unable to connect to remote server after Login'); phantom.exit(0);} if (!isSignedIn()) { if(mode =="cookie"){ if(fs.exists(cookiespath)) { @@ -190,50 +403,13 @@ function afterLogin(url, search, mode) { storeCookies(); } setupIITC() - setTimeout(function() { - if (search != 'nix') { - searchfunc(search); - } - waitFor({ - timeout: 240000, - check: function () { - return page.evaluate(function(zoomlevel) { - if (document.querySelector('.map').textContent.indexOf('done') != -1) { - return true; - }else{ - console.log('generateFakeOutput') - return false; - } - }, zoomlevel); - }, - success: function () { - var startTime = new Date().getTime(); - var interval = setInterval(function(){ - if(new Date().getTime() - startTime > 5000){ - hideDebris(); - prepare('1280', '720'); - main(); - clearInterval(interval); - return; - } - console.log('generateFakeOutput') - }, 1000); - }, - error: function () { - var startTime = new Date().getTime(); - var interval = setInterval(function(){ - if(new Date().getTime() - startTime > 5000){ - hideDebris(); - prepare('1280', '720'); - main(); - clearInterval(interval); - return; - } - console.log('generateFakeOutput') - }, 1000); - } - }); - }, "1000"); + if(screenshotfunction == "map"){ + map(search); + }else if (screenshotfunction == "portalinfoScreen"){ + portalinfoScreen(); + }else if (screenshotfunction == "portalinfoText"){ + portalinfoText(); + } }, "1000"); }); }