Created
September 26, 2016 16:49
-
-
Save pallada-92/fce7a5e1ad5f895b8c698061f30764be to your computer and use it in GitHub Desktop.
GChatStats
This file contains 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
{ | |
"cells": [ | |
{ | |
"cell_type": "raw", | |
"metadata": { | |
"collapsed": true | |
}, | |
"source": [ | |
"@contents @fj\n", | |
"1 e --- error handling\n", | |
"1 s --- state\n", | |
"1 w --- workers\n", | |
"123 p --- pages\n", | |
"1 a --- application\n", | |
"1 r --- render" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"http://localhost:8888/static/p/gchatstats/upload.html" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 1, | |
"metadata": { | |
"collapsed": false, | |
"init_cell": true | |
}, | |
"outputs": [], | |
"source": [ | |
"import nbformat\n", | |
"import extensions.my_ext\n", | |
"\n", | |
"# import importlib\n", | |
"# importlib.reload(extensions.my_ext)\n", | |
"\n", | |
"extensions.my_ext.load_ipython_extension(get_ipython())\n", | |
"\n", | |
"def make(fname):\n", | |
" source = open(fname, 'rb').read()\n", | |
" nb = nbformat.reads(source.decode('utf8'), as_version=4)\n", | |
" parents = {}\n", | |
" cells = [extensions.my_ext.NotebookCell(cell, parents, index) for index, cell in enumerate(nb.cells)]\n", | |
" with open('/data/sets/static/p/gchatstats/upload.html', 'w') as f:\n", | |
" f.write(make_html(cells))\n", | |
"\n", | |
"def make_html(cells):\n", | |
" header_html = ''\n", | |
" body_html = ''\n", | |
" jsx_scripts = ''\n", | |
" scripts = ''\n", | |
" run_scripts = ''\n", | |
" global_error = ''\n", | |
" for cell in cells:\n", | |
" if cell.magic == '%%js' and '@out' in cell.labels:\n", | |
" scripts += cell.get_output('application/javascript') + '\\n'\n", | |
" if cell.magic == '%%js' and '@out_run' in cell.labels:\n", | |
" run_scripts += cell.get_output('application/javascript') + '\\n'\n", | |
" if cell.magic == '%%js' and '@out_error' in cell.labels:\n", | |
" global_error += cell.source #('application/javascript') + '\\n'\n", | |
" elif cell.magic == '%%jsx' and '@out' in cell.labels:\n", | |
" jsx_scripts += cell.get_output('application/javascript') + '\\n'\n", | |
" elif cell.magic == '%%css' and '@out' in cell.labels:\n", | |
" header_html += cell.get_output('text/html') + '\\n'\n", | |
" elif cell.magic == '%%html' and '@header' in cell.labels:\n", | |
" header_html += cell.source + '\\n'\n", | |
" elif cell.magic == '%%html' and '@body' in cell.labels:\n", | |
" body_html += cell.source + '\\n'\n", | |
" elif cell.kind == 'code' and cell.source.startswith('%css '):\n", | |
" header_html += cell.get_output('text/html') + '\\n'\n", | |
" elif cell.magic == '%%requirejs':\n", | |
" require_config = cell.get_output('application/javascript') + '\\n'\n", | |
" res = '<!DOCTYPE html><html><head>\\n'\n", | |
" res += header_html + '\\n'\n", | |
" if hasattr(extensions.my_ext, 'requirejs'):\n", | |
" res += '<script src=\\\"%s\\\"></script>\\n' % extensions.my_ext.requirejs['lib_path']\n", | |
" res += '<script>\\n' + require_config + '\\n</script>\\n'\n", | |
" res += '<script>\\n' + global_error + '\\n</script>\\n'\n", | |
" res += '<script>\\n' + scripts + '\\n</script>\\n'\n", | |
" res += '<script>\\n' + jsx_scripts + '\\n</script>\\n'\n", | |
" res += '</head><body>\\n'\n", | |
" res += body_html\n", | |
" res += '<script>\\n' + run_scripts + '\\n</script>\\n'\n", | |
" res += '</body></html>\\n'\n", | |
" return res" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"metadata": { | |
"collapsed": false, | |
"hide_input": false, | |
"init_cell": true | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"application/javascript": [ | |
"require.config({paths:\n", | |
" {\n", | |
" \"jquery\": \"/static/jquery@2.1.1/jquery.min\",\n", | |
" \"react\": \"/static/react@15.3.1/build/react\"\n", | |
"}\n", | |
"});" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"execution_count": 2, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"%%requirejs /static/requirejs@2.3.1/require.min.js\n", | |
"$ jquery /static/jquery@2.1.1/jquery.min.js\n", | |
"React react /static/react@15.3.1/build/react.js\n", | |
"ReactDOM /static/react@15.3.1/build/react-dom.min.js\n", | |
"R /static/ramda@0.22.1/ramda.min.js\n", | |
"d3 /static/d3@4.2.2/d3.min.js\n", | |
"snap /static/snapsvg@0.4.1/dist/snap.svg-min.js\n", | |
"vis /static/visjs@4.16.1/dist/vis.min.js" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 3, | |
"metadata": { | |
"collapsed": false, | |
"init_cell": true | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"application/javascript": [ | |
"require([\"/static/react@15.3.1/build/react-dom.min.js\", \"/static/ramda@0.22.1/ramda.min.js\", \"jquery\", \"/static/snapsvg@0.4.1/dist/snap.svg-min.js\", \"react\", \"/static/visjs@4.16.1/dist/vis.min.js\", \"/static/d3@4.2.2/d3.min.js\"], function(ReactDOM, R, $, snap, React, vis, d3) {\n", | |
"if (window.location.hostname == 'localhost') {\n", | |
" window.server_path = 'http://localhost:8080';\n", | |
"} else {\n", | |
" window.server_path = 'http://example.com';\n", | |
"}\n", | |
"if (!window.IPython) {\n", | |
" $(function() {\n", | |
" reset();\n", | |
" render();\n", | |
" });\n", | |
"}\n", | |
"})" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"execution_count": 3, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"%%js @out_run\n", | |
"if (window.location.hostname == 'localhost') {\n", | |
" window.server_path = 'http://localhost:8080';\n", | |
"} else {\n", | |
" window.server_path = 'http://example.com';\n", | |
"}\n", | |
"if (!window.IPython) {\n", | |
" $(function() {\n", | |
" reset();\n", | |
" render();\n", | |
" });\n", | |
"}" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 4, | |
"metadata": { | |
"collapsed": false, | |
"init_cell": true | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"application/javascript": [ | |
"require([\"/static/react@15.3.1/build/react-dom.min.js\", \"/static/ramda@0.22.1/ramda.min.js\", \"jquery\", \"/static/snapsvg@0.4.1/dist/snap.svg-min.js\", \"react\", \"/static/visjs@4.16.1/dist/vis.min.js\", \"/static/d3@4.2.2/d3.min.js\"], function(ReactDOM, R, $, snap, React, vis, d3) {\n", | |
"\n", | |
"// http://stackoverflow.com/questions/5916900/how-can-you-detect-the-version-of-a-browser\n", | |
"window.get_browser = function(){\n", | |
" var ua=navigator.userAgent,tem,M=ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\\/))\\/?\\s*(\\d+)/i) || []; \n", | |
" if(/trident/i.test(M[1])){\n", | |
" tem=/\\brv[ :]+(\\d+)/g.exec(ua) || []; \n", | |
" return {name:'IE',version:(tem[1]||'')};\n", | |
" } \n", | |
" if(M[1]==='Chrome'){\n", | |
" tem=ua.match(/\\bOPR\\/(\\d+)/)\n", | |
" if(tem!=null) {return {name:'Opera', version:tem[1]};}\n", | |
" } \n", | |
" M=M[2]? [M[1], M[2]]: [navigator.appName, navigator.appVersion, '-?'];\n", | |
" if((tem=ua.match(/version\\/(\\d+)/i))!=null) {M.splice(1,1,tem[1]);}\n", | |
" return M[0] + ' ' + M[1];\n", | |
" }\n", | |
"\n", | |
"function get_debug_info() {\n", | |
" return {\n", | |
" hash: window.location.hash,\n", | |
" ipython: window.IPython,\n", | |
" browser: get_browser(),\n", | |
" state: window.state\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"window.onerror = function(msg, url, line, col, error) {\n", | |
" var message = \"Error: \" + msg + \"\\nurl: \" + url + \"\\nline: \" + line ;\n", | |
" message += !col ? '' : '\\ncolumn: ' + col;\n", | |
" message += !error ? '' : '\\nerror: ' + error;\n", | |
" console.log(message);\n", | |
" $.post(server_path + '/error', {\n", | |
" page : window.location.href.split('#')[0],\n", | |
" message : message,\n", | |
" info : JSON.stringify(get_debug_info()),\n", | |
" }, function() {\n", | |
" alert('Произошла ошибка.\\nИнформация отправлена администратору.\\nПопробуйте перезагрузить страницу и повторить запрос.')\n", | |
" }).fail(function() {\n", | |
" alert('Не удается связаться с сервером.\\n\\\n", | |
"Проверьте соединение и перезагрузите эту страницу.\\n\\\n", | |
"Если соединение не прерывалось, то это проблема на стороне сервера.\\n\\\n", | |
"В этом случае напишите на pallada-92@ya.ru');\n", | |
" });\n", | |
" return true;\n", | |
"};\n", | |
"})" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"execution_count": 4, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"%%js @out_error @1e\n", | |
"\n", | |
"// http://stackoverflow.com/questions/5916900/how-can-you-detect-the-version-of-a-browser\n", | |
"window.get_browser = function(){\n", | |
" var ua=navigator.userAgent,tem,M=ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\\/))\\/?\\s*(\\d+)/i) || []; \n", | |
" if(/trident/i.test(M[1])){\n", | |
" tem=/\\brv[ :]+(\\d+)/g.exec(ua) || []; \n", | |
" return {name:'IE',version:(tem[1]||'')};\n", | |
" } \n", | |
" if(M[1]==='Chrome'){\n", | |
" tem=ua.match(/\\bOPR\\/(\\d+)/)\n", | |
" if(tem!=null) {return {name:'Opera', version:tem[1]};}\n", | |
" } \n", | |
" M=M[2]? [M[1], M[2]]: [navigator.appName, navigator.appVersion, '-?'];\n", | |
" if((tem=ua.match(/version\\/(\\d+)/i))!=null) {M.splice(1,1,tem[1]);}\n", | |
" return M[0] + ' ' + M[1];\n", | |
" }\n", | |
"\n", | |
"function get_debug_info() {\n", | |
" return {\n", | |
" hash: window.location.hash,\n", | |
" ipython: window.IPython,\n", | |
" browser: get_browser(),\n", | |
" state: window.state\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"window.onerror = function(msg, url, line, col, error) {\n", | |
" var message = \"Error: \" + msg + \"\\nurl: \" + url + \"\\nline: \" + line ;\n", | |
" message += !col ? '' : '\\ncolumn: ' + col;\n", | |
" message += !error ? '' : '\\nerror: ' + error;\n", | |
" console.log(message);\n", | |
" $.post(server_path + '/error', {\n", | |
" page : window.location.href.split('#')[0],\n", | |
" message : message,\n", | |
" info : JSON.stringify(get_debug_info()),\n", | |
" }, function() {\n", | |
" alert('Произошла ошибка.\\nИнформация отправлена администратору.\\nПопробуйте перезагрузить страницу и повторить запрос.')\n", | |
" }).fail(function() {\n", | |
" alert('Не удается связаться с сервером.\\n\\\n", | |
"Проверьте соединение и перезагрузите эту страницу.\\n\\\n", | |
"Если соединение не прерывалось, то это проблема на стороне сервера.\\n\\\n", | |
"В этом случае напишите на pallada-92@ya.ru');\n", | |
" });\n", | |
" return true;\n", | |
"};" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 5, | |
"metadata": { | |
"collapsed": false, | |
"hide_input": false, | |
"init_cell": true | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<meta charset=\"utf-8\">\n", | |
"<title>Проанализировать групповой чат VK!</title>\n", | |
"<link href=\"https://fonts.googleapis.com/css?family=Roboto:400,300,500,700&subset=latin,cyrillic\" rel=\"stylesheet\" type=\"text/css\">" | |
], | |
"text/plain": [ | |
"<IPython.core.display.HTML object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"%%html @header\n", | |
"<meta charset=\"utf-8\">\n", | |
"<title>Проанализировать групповой чат VK!</title>\n", | |
"<link href=\"https://fonts.googleapis.com/css?family=Roboto:400,300,500,700&subset=latin,cyrillic\" rel=\"stylesheet\" type=\"text/css\">" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 6, | |
"metadata": { | |
"collapsed": false, | |
"init_cell": true | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<style>\n", | |
".css1 .root {\n", | |
" font-family: Roboto, Helvetica;\n", | |
" color: #333333;\n", | |
" background-color: white;\n", | |
"}\n", | |
".css1 .container {\n", | |
" position: relative;\n", | |
" width: 800px;\n", | |
" left: 50%;\n", | |
" margin-left: -400px;\n", | |
"}\n", | |
".css1 .link {\n", | |
" color: #5555EE;\n", | |
" cursor: pointer;\n", | |
" -webkit-transition: color 0.3s;\n", | |
" -moz-transition: color 0.3s;\n", | |
" -o-transition: color 0.3s;\n", | |
" transition: color 0.3s\n", | |
"}\n", | |
".css1 .link:hover {\n", | |
" color: #CC0000;\n", | |
"}\n", | |
".css1 .error {\n", | |
" color: #CC0000;\n", | |
" margin: 10px;\n", | |
"}\n", | |
".css1 li {\n", | |
" margin-bottom: 30px;\n", | |
"}\n", | |
".css1 h1 {\n", | |
" text-align: center;\n", | |
" font-size: 20px;\n", | |
" margin-bottom: 40px;\n", | |
" margin-top: 30px;\n", | |
" color: #333333;\n", | |
"}\n", | |
"\n", | |
"</style>" | |
], | |
"text/plain": [ | |
"<IPython.core.display.HTML object>" | |
] | |
}, | |
"execution_count": 6, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"%%css .css1 @out\n", | |
".root {\n", | |
" font-family: Roboto, Helvetica;\n", | |
" color: #333333;\n", | |
" background-color: white;\n", | |
"}\n", | |
".container {\n", | |
" position: relative;\n", | |
" width: 800px;\n", | |
" left: 50%;\n", | |
" margin-left: -400px;\n", | |
"}\n", | |
".link {\n", | |
" color: #5555EE;\n", | |
" cursor: pointer;\n", | |
" -webkit-transition: color 0.3s;\n", | |
" -moz-transition: color 0.3s;\n", | |
" -o-transition: color 0.3s;\n", | |
" transition: color 0.3s\n", | |
"}\n", | |
".link:hover {\n", | |
" color: #CC0000;\n", | |
"}\n", | |
".error {\n", | |
" color: #CC0000;\n", | |
" margin: 10px;\n", | |
"}\n", | |
"li {\n", | |
" margin-bottom: 30px;\n", | |
"}\n", | |
"h1 {\n", | |
" text-align: center;\n", | |
" font-size: 20px;\n", | |
" margin-bottom: 40px;\n", | |
" margin-top: 30px;\n", | |
" color: #333333;\n", | |
"}" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 7, | |
"metadata": { | |
"collapsed": false, | |
"init_cell": true | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<style>\n", | |
".css1 .remarks {\n", | |
" color: gray;\n", | |
" width: 100%;\n", | |
" padding-top: 40px;\n", | |
" text-align: left;\n", | |
"}\n", | |
".css1 .remark {\n", | |
" padding: 10px 0px;\n", | |
" display: inline-block;\n", | |
" width: 100%;\n", | |
" text-align: left;\n", | |
"}\n", | |
".css1 .remark2 {\n", | |
" padding: 10px 0px;\n", | |
" display: inline-block;\n", | |
" width: 50%;\n", | |
" text-align: left;\n", | |
"}\n", | |
"\n", | |
"</style>" | |
], | |
"text/plain": [ | |
"<IPython.core.display.HTML object>" | |
] | |
}, | |
"execution_count": 7, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"%%css .css1 @out\n", | |
".remarks {\n", | |
" color: gray;\n", | |
" width: 100%;\n", | |
" padding-top: 40px;\n", | |
" text-align: left;\n", | |
"}\n", | |
".remark {\n", | |
" padding: 10px 0px;\n", | |
" display: inline-block;\n", | |
" width: 100%;\n", | |
" text-align: left;\n", | |
"}\n", | |
".remark2 {\n", | |
" padding: 10px 0px;\n", | |
" display: inline-block;\n", | |
" width: 50%;\n", | |
" text-align: left;\n", | |
"}" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 8, | |
"metadata": { | |
"code_folding": [], | |
"collapsed": false, | |
"init_cell": true | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"application/javascript": [ | |
"require([\"/static/react@15.3.1/build/react-dom.min.js\", \"/static/ramda@0.22.1/ramda.min.js\", \"jquery\", \"/static/snapsvg@0.4.1/dist/snap.svg-min.js\", \"react\", \"/static/visjs@4.16.1/dist/vis.min.js\", \"/static/d3@4.2.2/d3.min.js\"], function(ReactDOM, R, $, snap, React, vis, d3) {\n", | |
"window.reset = function() {\n", | |
" window.consts = {\n", | |
" chat_names_step: 200,\n", | |
" messages_step: 200,\n", | |
" messages_limit: 2000\n", | |
" };\n", | |
" window.secret = {\n", | |
" token: undefined, \n", | |
" };\n", | |
" window.state = {\n", | |
" page: 1,\n", | |
" user_id: undefined,\n", | |
" chat_id: undefined,\n", | |
" chat_names_offset: 0,\n", | |
" chat_names_get: false,\n", | |
" chat_names_count: undefined,\n", | |
" hash: Math.round(Math.random() * 10000000000),\n", | |
" messages_get_offset: 0,\n", | |
" messages_post_offset: 0,\n", | |
" messages_all_count: undefined,\n", | |
" messages_count: undefined,\n", | |
" page3: 'get_messages' // 'post_messages' / 'get_users' / 'post_users' / 'finished'\n", | |
" };\n", | |
" window.cache = {\n", | |
" chat_names: [],\n", | |
" vk_requests_queue: [],\n", | |
" }\n", | |
"}\n", | |
"})" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"execution_count": 8, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"%%js @out @1s\n", | |
"window.reset = function() {\n", | |
" window.consts = {\n", | |
" chat_names_step: 200,\n", | |
" messages_step: 200,\n", | |
" messages_limit: 2000\n", | |
" };\n", | |
" window.secret = {\n", | |
" token: undefined, \n", | |
" };\n", | |
" window.state = {\n", | |
" page: 1,\n", | |
" user_id: undefined,\n", | |
" chat_id: undefined,\n", | |
" chat_names_offset: 0,\n", | |
" chat_names_get: false,\n", | |
" chat_names_count: undefined,\n", | |
" hash: Math.round(Math.random() * 10000000000),\n", | |
" messages_get_offset: 0,\n", | |
" messages_post_offset: 0,\n", | |
" messages_all_count: undefined,\n", | |
" messages_count: undefined,\n", | |
" page3: 'get_messages' // 'post_messages' / 'get_users' / 'post_users' / 'finished'\n", | |
" };\n", | |
" window.cache = {\n", | |
" chat_names: [],\n", | |
" vk_requests_queue: [],\n", | |
" }\n", | |
"}" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 9, | |
"metadata": { | |
"collapsed": false, | |
"init_cell": true | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"application/javascript": [ | |
"require([\"/static/react@15.3.1/build/react-dom.min.js\", \"/static/ramda@0.22.1/ramda.min.js\", \"jquery\", \"/static/snapsvg@0.4.1/dist/snap.svg-min.js\", \"react\", \"/static/visjs@4.16.1/dist/vis.min.js\", \"/static/d3@4.2.2/d3.min.js\"], function(ReactDOM, R, $, snap, React, vis, d3) {\n", | |
"window.generic_vk_request = function (method, params, ok_handler) {\n", | |
" let url = 'https://api.vk.com/method/' + method + '?callback=?';\n", | |
" $.getJSON(url, params).done(function(data, text){\n", | |
" if ('response' in data) {\n", | |
" ok_handler(data['response']);\n", | |
" } else {\n", | |
" throw JSON.stringify({url, data});\n", | |
" };\n", | |
" }).fail(function(jq, text, exception) {\n", | |
" let info = {jq, text, exception, url};\n", | |
" throw JSON.stringify(info);\n", | |
" });\n", | |
"}\n", | |
"})" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"execution_count": 9, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"%%js @out @1w\n", | |
"window.generic_vk_request = function (method, params, ok_handler) {\n", | |
" let url = 'https://api.vk.com/method/' + method + '?callback=?';\n", | |
" $.getJSON(url, params).done(function(data, text){\n", | |
" if ('response' in data) {\n", | |
" ok_handler(data['response']);\n", | |
" } else {\n", | |
" throw JSON.stringify({url, data});\n", | |
" };\n", | |
" }).fail(function(jq, text, exception) {\n", | |
" let info = {jq, text, exception, url};\n", | |
" throw JSON.stringify(info);\n", | |
" });\n", | |
"}" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 10, | |
"metadata": { | |
"collapsed": false, | |
"init_cell": true | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"application/javascript": [ | |
"require([\"/static/react@15.3.1/build/react-dom.min.js\", \"/static/ramda@0.22.1/ramda.min.js\", \"jquery\", \"/static/snapsvg@0.4.1/dist/snap.svg-min.js\", \"react\", \"/static/visjs@4.16.1/dist/vis.min.js\", \"/static/d3@4.2.2/d3.min.js\"], function(ReactDOM, R, $, snap, React, vis, d3) {\n", | |
"window.generic_server_request = function (method, params, ok_handler) {\n", | |
" let url = server_path + '/' + method;\n", | |
" $.post(url, params).done(function(data, text){\n", | |
" ok_handler(data);\n", | |
" }).fail(function(jq, text, exception) {\n", | |
" let info = {jq, text, exception, url};\n", | |
" throw JSON.stringify(info);\n", | |
" });\n", | |
"}\n", | |
"})" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"execution_count": 10, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"%%js @out\n", | |
"window.generic_server_request = function (method, params, ok_handler) {\n", | |
" let url = server_path + '/' + method;\n", | |
" $.post(url, params).done(function(data, text){\n", | |
" ok_handler(data);\n", | |
" }).fail(function(jq, text, exception) {\n", | |
" let info = {jq, text, exception, url};\n", | |
" throw JSON.stringify(info);\n", | |
" });\n", | |
"}" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 11, | |
"metadata": { | |
"collapsed": false, | |
"init_cell": true | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Starting react...\n" | |
] | |
}, | |
{ | |
"data": { | |
"application/javascript": [ | |
"\"use strict\";\n", | |
"\n", | |
"require([\"/static/react@15.3.1/build/react-dom.min.js\", \"/static/ramda@0.22.1/ramda.min.js\", \"jquery\", \"/static/snapsvg@0.4.1/dist/snap.svg-min.js\", \"react\", \"/static/visjs@4.16.1/dist/vis.min.js\", \"/static/d3@4.2.2/d3.min.js\"], function (ReactDOM, R, $, snap, React, vis, d3) {\n", | |
" window.get_chat_names = function () {\n", | |
" generic_vk_request('messages.getDialogs', {\n", | |
" access_token: secret.token,\n", | |
" offset: state.chat_names_offset,\n", | |
" count: consts.chat_names_step,\n", | |
" v: '5.38'\n", | |
" }, function (response) {\n", | |
" state.chat_names_count = response.count;\n", | |
" state.chat_names_offset += consts.chat_names_step;\n", | |
" console.log(response);\n", | |
" // Group chats are those, which have users_count field\n", | |
" var group_chats = R.filter(R.pathSatisfies(R.complement(R.equals(undefined)), ['message', 'users_count']), response.items);\n", | |
" // For each group chat, get pair [chat_id, title] and save it to state.chat_names\n", | |
" cache.chat_names = cache.chat_names.concat(R.map(R.juxt([R.path(['message', 'chat_id']), R.path(['message', 'title'])]), group_chats));\n", | |
" if (state.chat_names_offset < state.chat_names_count && state.page == 2) {\n", | |
" setTimeout(get_chat_names, 500);\n", | |
" } else if (state.chat_names_offset >= state.chat_names_count) {\n", | |
" state.chat_names_get = true;\n", | |
" }\n", | |
" render();\n", | |
" });\n", | |
" };\n", | |
"});" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"execution_count": 11, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"%%jsx @out\n", | |
"window.get_chat_names = function() {\n", | |
" generic_vk_request('messages.getDialogs', {\n", | |
" access_token: secret.token,\n", | |
" offset: state.chat_names_offset,\n", | |
" count: consts.chat_names_step,\n", | |
" v: '5.38',\n", | |
" }, (response) => {\n", | |
" state.chat_names_count = response.count;\n", | |
" state.chat_names_offset += consts.chat_names_step;\n", | |
" console.log(response);\n", | |
" // Group chats are those, which have users_count field\n", | |
" let group_chats = R.filter(\n", | |
" R.pathSatisfies(\n", | |
" R.complement(R.equals(undefined)),\n", | |
" ['message', 'users_count']\n", | |
" ),\n", | |
" response.items\n", | |
" );\n", | |
" // For each group chat, get pair [chat_id, title] and save it to state.chat_names\n", | |
" cache.chat_names = cache.chat_names.concat(R.map(\n", | |
" R.juxt([R.path(['message', 'chat_id']), R.path(['message', 'title'])]),\n", | |
" group_chats\n", | |
" ));\n", | |
" if (state.chat_names_offset < state.chat_names_count && state.page == 2) {\n", | |
" setTimeout(get_chat_names, 500);\n", | |
" } else if (state.chat_names_offset >= state.chat_names_count) {\n", | |
" state.chat_names_get = true;\n", | |
" }\n", | |
" render();\n", | |
" });\n", | |
"}" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 150, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"application/javascript": [ | |
"\"use strict\";\n", | |
"\n", | |
"require([\"/static/react@15.3.1/build/react-dom.min.js\", \"react\", \"jquery\", \"/static/visjs@4.16.1/dist/vis.min.js\", \"/static/snapsvg@0.4.1/dist/snap.svg-min.js\", \"/static/d3@4.2.2/d3.min.js\", \"/static/ramda@0.22.1/ramda.min.js\"], function (ReactDOM, React, $, vis, snap, d3, R) {\n", | |
" get_chat_names();\n", | |
"});" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"execution_count": 150, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"%%jsx\n", | |
"get_chat_names();" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 12, | |
"metadata": { | |
"collapsed": false, | |
"init_cell": true | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"application/javascript": [ | |
"\"use strict\";\n", | |
"\n", | |
"require([\"/static/react@15.3.1/build/react-dom.min.js\", \"/static/ramda@0.22.1/ramda.min.js\", \"jquery\", \"/static/snapsvg@0.4.1/dist/snap.svg-min.js\", \"react\", \"/static/visjs@4.16.1/dist/vis.min.js\", \"/static/d3@4.2.2/d3.min.js\"], function (ReactDOM, R, $, snap, React, vis, d3) {\n", | |
"\n", | |
" window.get_users = function () {\n", | |
" state.page3 = 'get_users';\n", | |
" generic_vk_request('messages.getChatUsers', {\n", | |
" access_token: secret.token,\n", | |
" chat_id: state.chat_id,\n", | |
" fields: 'screen_name, photo_50, photo_100, photo_200_orig',\n", | |
" v: '5.38'\n", | |
" }, function (response) {\n", | |
" console.log(response);\n", | |
" cache.chat_users = response;\n", | |
" if (state.page == 3) {\n", | |
" setTimeout(post_users, 300);\n", | |
" }\n", | |
" render();\n", | |
" });\n", | |
" };\n", | |
"\n", | |
" window.post_users = function () {\n", | |
" state.page3 = 'post_users';\n", | |
" console.log(JSON.stringify(cache.chat_users));\n", | |
" generic_server_request('upload_vk_users', {\n", | |
" user_id: state.user_id,\n", | |
" chat_id: state.chat_id,\n", | |
" hash: state.hash,\n", | |
" users_data: JSON.stringify(cache.chat_users)\n", | |
" }, function (response) {\n", | |
" get_messages();\n", | |
" render();\n", | |
" });\n", | |
" };\n", | |
"\n", | |
" window.get_messages = function () {\n", | |
" state.page3 = 'get_messages';\n", | |
" console.log('get_messages', state.chat_id);\n", | |
" generic_vk_request('messages.getHistory', {\n", | |
" access_token: secret.token,\n", | |
" offset: state.messages_get_offset,\n", | |
" count: consts.messages_step,\n", | |
" peer_id: 2000000000 + state.chat_id,\n", | |
" v: '5.38'\n", | |
" }, function (response) {\n", | |
" console.log('resp', response);\n", | |
" state.messages_all_count = response.count;\n", | |
" state.messages_count = Math.min(state.messages_all_count, consts.messages_limit);\n", | |
" console.log('resp1');\n", | |
" state.messages_get_offset += consts.messages_step;\n", | |
" cache.messages = response.items;\n", | |
" console.log('setting timeout1', state.page);\n", | |
" if (state.page == 3) {\n", | |
" console.log('setting timeout');\n", | |
" setTimeout(post_messages, 300);\n", | |
" }\n", | |
" render();\n", | |
" });\n", | |
" };\n", | |
"\n", | |
" window.post_messages = function () {\n", | |
" state.page3 = 'post_messages';\n", | |
" generic_server_request('upload_vk_messages', {\n", | |
" offset: state.messages_offset,\n", | |
" hash: state.hash,\n", | |
" messages: JSON.stringify(cache.messages)\n", | |
" }, function (response) {\n", | |
" state.messages_post_offset += consts.messages_step;\n", | |
" var limit_reached = state.messages_get_offset >= state.messages_count;\n", | |
" if (!limit_reached && state.page == 3) {\n", | |
" setTimeout(get_messages, 300);\n", | |
" } else if (limit_reached && state.page == 3) {\n", | |
" state.messages_loaded = true;\n", | |
" setTimeout(finalize_upload, 300);\n", | |
" }\n", | |
" render();\n", | |
" });\n", | |
" };\n", | |
"\n", | |
" window.finalize_upload = function () {\n", | |
" state.page3 = 'finalizing';\n", | |
" generic_server_request('upload_vk_finalize', {\n", | |
" hash: state.hash\n", | |
" }, function (response) {\n", | |
" state.page3 = 'finalized';\n", | |
" render();\n", | |
" });\n", | |
" };\n", | |
"});" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"execution_count": 12, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"%%jsx @out @2w\n", | |
"\n", | |
"window.get_users = function() {\n", | |
" state.page3 = 'get_users';\n", | |
" generic_vk_request('messages.getChatUsers', {\n", | |
" access_token: secret.token,\n", | |
" chat_id: state.chat_id,\n", | |
" fields: 'screen_name, photo_50, photo_100, photo_200_orig',\n", | |
" v: '5.38',\n", | |
" }, (response) => {\n", | |
" console.log(response);\n", | |
" cache.chat_users = response;\n", | |
" if (state.page == 3) {\n", | |
" setTimeout(post_users, 300);\n", | |
" }\n", | |
" render();\n", | |
" });\n", | |
"}\n", | |
"\n", | |
"window.post_users = function() {\n", | |
" state.page3 = 'post_users';\n", | |
" console.log(JSON.stringify(cache.chat_users));\n", | |
" generic_server_request('upload_vk_users', {\n", | |
" user_id: state.user_id,\n", | |
" chat_id: state.chat_id,\n", | |
" chat_name: cache.chat_names[state.chat_id],\n", | |
" hash: state.hash,\n", | |
" users_data: JSON.stringify(cache.chat_users),\n", | |
" }, (response) => {\n", | |
" get_messages();\n", | |
" render();\n", | |
" });\n", | |
"}\n", | |
"\n", | |
"window.get_messages = function() {\n", | |
" state.page3 = 'get_messages';\n", | |
" console.log('get_messages', state.chat_id);\n", | |
" generic_vk_request('messages.getHistory', {\n", | |
" access_token: secret.token,\n", | |
" offset: state.messages_get_offset,\n", | |
" count: consts.messages_step,\n", | |
" peer_id: 2000000000 + state.chat_id,\n", | |
" v: '5.38',\n", | |
" }, (response) => {\n", | |
" console.log('resp', response);\n", | |
" state.messages_all_count = response.count;\n", | |
" state.messages_count = Math.min(state.messages_all_count, consts.messages_limit);\n", | |
" console.log('resp1');\n", | |
" state.messages_get_offset += consts.messages_step;\n", | |
" cache.messages = response.items;\n", | |
" console.log('setting timeout1', state.page);\n", | |
" if (state.page == 3) {\n", | |
" console.log('setting timeout');\n", | |
" setTimeout(post_messages, 300);\n", | |
" }\n", | |
" render();\n", | |
" });\n", | |
"}\n", | |
"\n", | |
"window.post_messages = function() {\n", | |
" state.page3 = 'post_messages';\n", | |
" generic_server_request('upload_vk_messages', {\n", | |
" offset: state.messages_offset,\n", | |
" hash: state.hash,\n", | |
" messages: JSON.stringify(cache.messages),\n", | |
" }, (response) => {\n", | |
" state.messages_post_offset += consts.messages_step;\n", | |
" let limit_reached = state.messages_get_offset >= state.messages_count;\n", | |
" if (!limit_reached && state.page == 3) {\n", | |
" setTimeout(get_messages, 300);\n", | |
" } else if (limit_reached && state.page == 3) {\n", | |
" state.messages_loaded = true;\n", | |
" setTimeout(finalize_upload, 300);\n", | |
" }\n", | |
" render();\n", | |
" })\n", | |
"}\n", | |
"\n", | |
"window.finalize_upload = function() {\n", | |
" state.page3 = 'finalizing';\n", | |
" generic_server_request('upload_vk_finalize', {\n", | |
" hash: state.hash,\n", | |
" }, (response) => {\n", | |
" state.page3 = 'finalized';\n", | |
" render();\n", | |
" });\n", | |
"}" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 13, | |
"metadata": { | |
"collapsed": false, | |
"init_cell": true | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"application/javascript": [ | |
"\"use strict\";\n", | |
"\n", | |
"require([\"/static/react@15.3.1/build/react-dom.min.js\", \"/static/ramda@0.22.1/ramda.min.js\", \"jquery\", \"/static/snapsvg@0.4.1/dist/snap.svg-min.js\", \"react\", \"/static/visjs@4.16.1/dist/vis.min.js\", \"/static/d3@4.2.2/d3.min.js\"], function (ReactDOM, R, $, snap, React, vis, d3) {\n", | |
" window.check_addr_syntax = function (addr) {\n", | |
" var s1 = \"https://oauth.vk.com/blank.html#access_token=\";\n", | |
" var s2 = \"&expires_in=\";\n", | |
" var s3 = \"&user_id=\";\n", | |
" var p1 = addr.indexOf(s1);\n", | |
" if (p1 == -1) return { error: \"Адрес должен начинаться с \\\"https://oauth.vk.com/blank.html#access_token=\\\"\" };\n", | |
" var p2 = p1 + s1.length;\n", | |
" var p3 = addr.indexOf(s2);\n", | |
" if (p3 == -1) return { error: \"В адресе должно быть поле \\\"&expires_in=\\\"\" };\n", | |
" var token = addr.slice(p2, p3);\n", | |
" var p4 = p3 + s2.length;\n", | |
" var p5 = addr.indexOf(s3);\n", | |
" if (p5 == -1) return { error: \"В адресе должно быть поле \\\"&user_id=\\\"\" };\n", | |
" var expires = addr.slice(p4, p5);\n", | |
" var p6 = p5 + s3.length;\n", | |
" var p7 = addr.length;\n", | |
" var user_id = addr.slice(p6, p7);\n", | |
" if (!/^[0-9a-f]*$/.test(token) || token == '') return { error: \"Некорректный токен \\\"\" + token + \"\\\"\" };\n", | |
" if (!/^[0-9]*$/.test(user_id) || user_id == '') return { error: \"Некорректный user_id \\\"\" + user_id + \"\\\"\" };\n", | |
" return { token: token, user_id: user_id };\n", | |
" };\n", | |
"});" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"execution_count": 13, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"%%jsx @out\n", | |
"window.check_addr_syntax = function (addr) {\n", | |
" var s1 = \"https://oauth.vk.com/blank.html#access_token=\";\n", | |
" var s2 = \"&expires_in=\";\n", | |
" var s3 = \"&user_id=\";\n", | |
" var p1 = addr.indexOf(s1);\n", | |
" if (p1 == -1) return {error: \"Адрес должен начинаться с \\\"https://oauth.vk.com/blank.html#access_token=\\\"\"};\n", | |
" var p2 = p1 + s1.length;\n", | |
" var p3 = addr.indexOf(s2);\n", | |
" if (p3 == -1) return {error: \"В адресе должно быть поле \\\"&expires_in=\\\"\"};\n", | |
" var token = addr.slice(p2, p3);\n", | |
" var p4 = p3 + s2.length;\n", | |
" var p5 = addr.indexOf(s3);\n", | |
" if (p5 == -1) return {error: \"В адресе должно быть поле \\\"&user_id=\\\"\"};\n", | |
" var expires = addr.slice(p4, p5);\n", | |
" var p6 = p5 + s3.length;\n", | |
" var p7 = addr.length;\n", | |
" var user_id = addr.slice(p6, p7);\n", | |
" if (!(/^[0-9a-f]*$/.test(token)) || token == '') return {error: \"Некорректный токен \\\"\" + token+ \"\\\"\"};\n", | |
" if (!(/^[0-9]*$/.test(user_id)) || user_id == '') return {error: \"Некорректный user_id \\\"\" + user_id + \"\\\"\"};\n", | |
" return {token, user_id};\n", | |
"}" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 14, | |
"metadata": { | |
"collapsed": false, | |
"init_cell": true | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"application/javascript": [ | |
"\"use strict\";\n", | |
"\n", | |
"require([\"/static/react@15.3.1/build/react-dom.min.js\", \"/static/ramda@0.22.1/ramda.min.js\", \"jquery\", \"/static/snapsvg@0.4.1/dist/snap.svg-min.js\", \"react\", \"/static/visjs@4.16.1/dist/vis.min.js\", \"/static/d3@4.2.2/d3.min.js\"], function (ReactDOM, R, $, snap, React, vis, d3) {\n", | |
" window.Action = React.createClass({\n", | |
" displayName: \"Action\",\n", | |
"\n", | |
" render: function render() {\n", | |
" return React.createElement(\n", | |
" \"div\",\n", | |
" { style: { textAlign: 'center', margin: 20 } },\n", | |
" React.createElement(\n", | |
" \"span\",\n", | |
" { className: \"link\", onClick: this.props.handler },\n", | |
" this.props.text\n", | |
" )\n", | |
" );\n", | |
" }\n", | |
" });\n", | |
"});" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"execution_count": 14, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"%%jsx @out\n", | |
"window.Action = React.createClass({\n", | |
" render: function() {\n", | |
" return <div style={{textAlign: 'center', margin: 20}}>\n", | |
" <span className=\"link\" onClick={this.props.handler}>\n", | |
" {this.props.text} \n", | |
" </span>\n", | |
" </div>;\n", | |
" }\n", | |
"});" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 15, | |
"metadata": { | |
"collapsed": false, | |
"init_cell": true | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"application/javascript": [ | |
"\"use strict\";\n", | |
"\n", | |
"var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"]) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); } }; }();\n", | |
"\n", | |
"require([\"/static/react@15.3.1/build/react-dom.min.js\", \"/static/ramda@0.22.1/ramda.min.js\", \"jquery\", \"/static/snapsvg@0.4.1/dist/snap.svg-min.js\", \"react\", \"/static/visjs@4.16.1/dist/vis.min.js\", \"/static/d3@4.2.2/d3.min.js\"], function (ReactDOM, R, $, snap, React, vis, d3) {\n", | |
" window.Actions = React.createClass({\n", | |
" displayName: \"Actions\",\n", | |
"\n", | |
" render: function render() {\n", | |
" var _this = this;\n", | |
"\n", | |
" var actions = R.map(function (_ref) {\n", | |
" var _ref2 = _slicedToArray(_ref, 2);\n", | |
"\n", | |
" var id = _ref2[0];\n", | |
" var title = _ref2[1];\n", | |
" return React.createElement(Action, { handler: _this.props.handler.bind(_this, id), text: title, key: id });\n", | |
" }, this.props.list);\n", | |
" return React.createElement(\n", | |
" \"div\",\n", | |
" null,\n", | |
" actions\n", | |
" );\n", | |
" }\n", | |
" });\n", | |
"});" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"execution_count": 15, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"%%jsx @out\n", | |
"window.Actions = React.createClass({\n", | |
" render: function() {\n", | |
" let actions = R.map(\n", | |
" ([id, title]) => <Action handler={this.props.handler.bind(this, id)} text={title} key={id}/>,\n", | |
" this.props.list\n", | |
" );\n", | |
" return <div>{actions}</div>;\n", | |
" }\n", | |
"});" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 16, | |
"metadata": { | |
"collapsed": false, | |
"init_cell": true | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"application/javascript": [ | |
"\"use strict\";\n", | |
"\n", | |
"require([\"/static/react@15.3.1/build/react-dom.min.js\", \"/static/ramda@0.22.1/ramda.min.js\", \"jquery\", \"/static/snapsvg@0.4.1/dist/snap.svg-min.js\", \"react\", \"/static/visjs@4.16.1/dist/vis.min.js\", \"/static/d3@4.2.2/d3.min.js\"], function (ReactDOM, R, $, snap, React, vis, d3) {\n", | |
" window.Errors = React.createClass({\n", | |
" displayName: \"Errors\",\n", | |
"\n", | |
" render: function render() {\n", | |
" var errors = R.map(function (error) {\n", | |
" return React.createElement(\n", | |
" \"div\",\n", | |
" { key: error, className: \"error\" },\n", | |
" error\n", | |
" );\n", | |
" }, this.props.data);\n", | |
" return React.createElement(\n", | |
" \"div\",\n", | |
" null,\n", | |
" errors\n", | |
" );\n", | |
" }\n", | |
" });\n", | |
"});" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"execution_count": 16, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"%%jsx @out\n", | |
"window.Errors = React.createClass({\n", | |
" render: function() {\n", | |
" let errors = R.map(\n", | |
" (error) => <div key={error} className=\"error\">{error}</div>,\n", | |
" this.props.data\n", | |
" );\n", | |
" return (\n", | |
" <div>\n", | |
" {errors}\n", | |
" </div>\n", | |
" );\n", | |
" }\n", | |
"});" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 17, | |
"metadata": { | |
"collapsed": false, | |
"init_cell": true | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"application/javascript": [ | |
"\"use strict\";\n", | |
"\n", | |
"require([\"/static/react@15.3.1/build/react-dom.min.js\", \"/static/ramda@0.22.1/ramda.min.js\", \"jquery\", \"/static/snapsvg@0.4.1/dist/snap.svg-min.js\", \"react\", \"/static/visjs@4.16.1/dist/vis.min.js\", \"/static/d3@4.2.2/d3.min.js\"], function (ReactDOM, R, $, snap, React, vis, d3) {\n", | |
" window.Progress = React.createClass({\n", | |
" displayName: \"Progress\",\n", | |
"\n", | |
" render: function render() {\n", | |
" var preload_percent = this.props.preload * 100,\n", | |
" load_percent = this.props.value * 100;\n", | |
" var outer_style = {\n", | |
" height: 25,\n", | |
" borderRadius: 5,\n", | |
" border: '1px solid gray',\n", | |
" position: 'relative',\n", | |
" overflow: 'hidden'\n", | |
" },\n", | |
" preload_style = {\n", | |
" position: 'absolute',\n", | |
" backgroundColor: 'rgb(228, 243, 243)',\n", | |
" width: preload_percent + '%',\n", | |
" height: 25,\n", | |
" top: 0,\n", | |
" left: 0\n", | |
" },\n", | |
" load_style = {\n", | |
" position: 'absolute',\n", | |
" backgroundColor: 'lightblue',\n", | |
" width: load_percent + '%',\n", | |
" height: 25,\n", | |
" top: 0,\n", | |
" left: 0\n", | |
" },\n", | |
" text_style = {\n", | |
" fontSize: 15,\n", | |
" position: 'absolute',\n", | |
" color: '#555555',\n", | |
" top: 3,\n", | |
" left: 0,\n", | |
" width: '100%',\n", | |
" height: 20,\n", | |
" textAlign: 'center'\n", | |
" };\n", | |
" return React.createElement(\n", | |
" \"div\",\n", | |
" { style: outer_style },\n", | |
" React.createElement(\"div\", { style: preload_style }),\n", | |
" React.createElement(\"div\", { style: load_style }),\n", | |
" React.createElement(\n", | |
" \"div\",\n", | |
" { style: text_style },\n", | |
" this.props.text\n", | |
" )\n", | |
" );\n", | |
" }\n", | |
" });\n", | |
"});" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"execution_count": 17, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"%%jsx @out\n", | |
"window.Progress = React.createClass({\n", | |
" render: function() {\n", | |
" let preload_percent = this.props.preload * 100,\n", | |
" load_percent = this.props.value * 100;\n", | |
" let outer_style = {\n", | |
" height: 25,\n", | |
" borderRadius: 5,\n", | |
" border: '1px solid gray',\n", | |
" position: 'relative',\n", | |
" overflow: 'hidden'\n", | |
" }, preload_style = {\n", | |
" position: 'absolute',\n", | |
" backgroundColor: 'rgb(228, 243, 243)',\n", | |
" width: preload_percent + '%',\n", | |
" height: 25,\n", | |
" top: 0,\n", | |
" left: 0,\n", | |
" }, load_style = {\n", | |
" position: 'absolute',\n", | |
" backgroundColor: 'lightblue',\n", | |
" width: load_percent + '%',\n", | |
" height: 25,\n", | |
" top: 0,\n", | |
" left: 0,\n", | |
" }, text_style = {\n", | |
" fontSize: 15,\n", | |
" position: 'absolute',\n", | |
" color: '#555555',\n", | |
" top: 3,\n", | |
" left: 0,\n", | |
" width: '100%',\n", | |
" height: 20,\n", | |
" textAlign: 'center'\n", | |
" }\n", | |
" return (\n", | |
" <div style={outer_style}>\n", | |
" <div style={preload_style}/>\n", | |
" <div style={load_style}/>\n", | |
" <div style={text_style}>{this.props.text}</div>\n", | |
" </div>\n", | |
" );\n", | |
" }\n", | |
"});" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 18, | |
"metadata": { | |
"collapsed": false, | |
"init_cell": true | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"application/javascript": [ | |
"\"use strict\";\n", | |
"\n", | |
"require([\"/static/react@15.3.1/build/react-dom.min.js\", \"/static/ramda@0.22.1/ramda.min.js\", \"jquery\", \"/static/snapsvg@0.4.1/dist/snap.svg-min.js\", \"react\", \"/static/visjs@4.16.1/dist/vis.min.js\", \"/static/d3@4.2.2/d3.min.js\"], function (ReactDOM, R, $, snap, React, vis, d3) {\n", | |
" window.Textarea = React.createClass({\n", | |
" displayName: \"Textarea\",\n", | |
"\n", | |
" render: function render() {\n", | |
" var _this = this;\n", | |
"\n", | |
" var handler = function handler(event) {\n", | |
" _this.props.handler(event.target.value);\n", | |
" };\n", | |
" var style = { minWidth: '95%', minHeight: 50, padding: 5 };\n", | |
" return React.createElement(\"textarea\", { style: style, ref: \"textarea\", onChange: handler, value: this.props.value });\n", | |
" }\n", | |
" });\n", | |
"});" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"execution_count": 18, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"%%jsx @out\n", | |
"window.Textarea = React.createClass({\n", | |
" render: function() {\n", | |
" let handler = (event) => {\n", | |
" this.props.handler(event.target.value);\n", | |
" };\n", | |
" let style = {minWidth: '95%', minHeight: 50, padding: 5};\n", | |
" return (\n", | |
" <textarea style={style} ref=\"textarea\" onChange={handler} value={this.props.value}/>\n", | |
" );\n", | |
" }\n", | |
"});" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 19, | |
"metadata": { | |
"collapsed": false, | |
"init_cell": true | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"application/javascript": [ | |
"\"use strict\";\n", | |
"\n", | |
"require([\"/static/react@15.3.1/build/react-dom.min.js\", \"/static/ramda@0.22.1/ramda.min.js\", \"jquery\", \"/static/snapsvg@0.4.1/dist/snap.svg-min.js\", \"react\", \"/static/visjs@4.16.1/dist/vis.min.js\", \"/static/d3@4.2.2/d3.min.js\"], function (ReactDOM, R, $, snap, React, vis, d3) {\n", | |
" window.FirstPage = React.createClass({\n", | |
" displayName: \"FirstPage\",\n", | |
"\n", | |
" getInitialState: function getInitialState() {\n", | |
" return { value: '', errors: [] };\n", | |
" },\n", | |
" valChange: function valChange(value) {\n", | |
" var errors = [];\n", | |
" var parse_res = check_addr_syntax(value);\n", | |
" if ('error' in parse_res) {\n", | |
" if (value != '') {\n", | |
" errors.push(parse_res.error);\n", | |
" this.setState({ value: value, errors: errors });\n", | |
" }\n", | |
" } else {\n", | |
" state.page = 2;\n", | |
" secret.token = parse_res.token;\n", | |
" state.user_id = parse_res.user_id;\n", | |
" get_chat_names();\n", | |
" render();\n", | |
" }\n", | |
" },\n", | |
" render: function render() {\n", | |
" var href = \"https://oauth.vk.com/authorize?client_id=4910996&redirect_uri=\";\n", | |
" href += \"https://oauth.vk.com/blank.html&display=page&scope=4096&response_type=token\";\n", | |
" return React.createElement(\n", | |
" \"div\",\n", | |
" null,\n", | |
" React.createElement(\n", | |
" \"h1\",\n", | |
" null,\n", | |
" \"Получение токена для анализа групповых чатов\"\n", | |
" ),\n", | |
" React.createElement(\n", | |
" \"ul\",\n", | |
" null,\n", | |
" React.createElement(\n", | |
" \"li\",\n", | |
" null,\n", | |
" \"Перейдите по \",\n", | |
" React.createElement(\n", | |
" \"a\",\n", | |
" { href: href,\n", | |
" target: \"_blank\", className: \"link\" },\n", | |
" \"ссылке\"\n", | |
" ),\n", | |
" \" в новом окне.\"\n", | |
" ),\n", | |
" React.createElement(\n", | |
" \"li\",\n", | |
" null,\n", | |
" \"Разрешите приложению GroupChatStats доступ к работе с личными сообщениями.\"\n", | |
" ),\n", | |
" React.createElement(\n", | |
" \"li\",\n", | |
" null,\n", | |
" \" Вы должны увидеть текст \\\"Пожалуйста, не копируйте данные из адресной строки...\\\"\"\n", | |
" ),\n", | |
" React.createElement(\n", | |
" \"li\",\n", | |
" null,\n", | |
" \" Скопируйте данные из адресной строки, закройте окно и вставьте их сюда:\",\n", | |
" React.createElement(\"br\", null),\n", | |
" React.createElement(\"br\", null),\n", | |
" React.createElement(Textarea, { handler: this.valChange, value: this.state.value }),\n", | |
" React.createElement(Errors, { data: this.state.errors })\n", | |
" )\n", | |
" ),\n", | |
" React.createElement(\n", | |
" \"div\",\n", | |
" { className: \"remarks\" },\n", | |
" React.createElement(\n", | |
" \"div\",\n", | |
" { className: \"remark\" },\n", | |
" \"Токен не передается на сервер и используется исключительно для чтения истории выбранного группового чата.\"\n", | |
" )\n", | |
" )\n", | |
" );\n", | |
" }\n", | |
" });\n", | |
"});" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"execution_count": 19, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"%%jsx @out @1p\n", | |
"window.FirstPage = React.createClass({\n", | |
" getInitialState: function() {\n", | |
" return {value: '', errors: []};\n", | |
" },\n", | |
" valChange: function(value) {\n", | |
" let errors = [];\n", | |
" let parse_res = check_addr_syntax(value);\n", | |
" if ('error' in parse_res) {\n", | |
" if (value != '') {\n", | |
" errors.push(parse_res.error);\n", | |
" this.setState({value, errors});\n", | |
" }\n", | |
" } else {\n", | |
" state.page = 2;\n", | |
" secret.token = parse_res.token;\n", | |
" state.user_id = parse_res.user_id;\n", | |
" get_chat_names();\n", | |
" render();\n", | |
" }\n", | |
" },\n", | |
" render: function() {\n", | |
" let href = \"https://oauth.vk.com/authorize?client_id=4910996&redirect_uri=\";\n", | |
" href += \"https://oauth.vk.com/blank.html&display=page&scope=4096&response_type=token\";\n", | |
" return (\n", | |
" <div>\n", | |
" <h1>Получение токена для анализа групповых чатов</h1>\n", | |
" <ul>\n", | |
" <li>Перейдите по \n", | |
" <a href={href}\n", | |
" target=\"_blank\" className=\"link\">ссылке</a> в новом окне.</li>\n", | |
" <li>Разрешите приложению GroupChatStats доступ к работе с личными сообщениями.</li>\n", | |
" <li> Вы должны увидеть текст \"Пожалуйста, не копируйте данные из адресной строки...\"</li>\n", | |
" <li> Скопируйте данные из адресной строки, закройте окно и вставьте их сюда:<br/><br/>\n", | |
" <Textarea handler={this.valChange} value={this.state.value}/>\n", | |
" <Errors data={this.state.errors}/> \n", | |
" </li>\n", | |
" </ul>\n", | |
" <div className=\"remarks\">\n", | |
" <div className=\"remark\">\n", | |
" Токен не передается на сервер и используется исключительно для чтения истории выбранного группового чата.\n", | |
" </div>\n", | |
" </div>\n", | |
" </div>\n", | |
" );\n", | |
" }\n", | |
"});" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 20, | |
"metadata": { | |
"collapsed": false, | |
"init_cell": true | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"application/javascript": [ | |
"\"use strict\";\n", | |
"\n", | |
"require([\"/static/react@15.3.1/build/react-dom.min.js\", \"/static/ramda@0.22.1/ramda.min.js\", \"jquery\", \"/static/snapsvg@0.4.1/dist/snap.svg-min.js\", \"react\", \"/static/visjs@4.16.1/dist/vis.min.js\", \"/static/d3@4.2.2/d3.min.js\"], function (ReactDOM, R, $, snap, React, vis, d3) {\n", | |
" window.SecondPage = React.createClass({\n", | |
" displayName: \"SecondPage\",\n", | |
"\n", | |
" render: function (_render) {\n", | |
" function render() {\n", | |
" return _render.apply(this, arguments);\n", | |
" }\n", | |
"\n", | |
" render.toString = function () {\n", | |
" return _render.toString();\n", | |
" };\n", | |
"\n", | |
" return render;\n", | |
" }(function () {\n", | |
" var handler = function handler(chat_id) {\n", | |
" state.page = 3;\n", | |
" state.chat_id = chat_id;\n", | |
" get_users();\n", | |
" render();\n", | |
" };\n", | |
" var title = state.chat_names_get ? 'Выберите чат для анализа' : 'Идет получение списка чатов...';\n", | |
" return React.createElement(\n", | |
" \"div\",\n", | |
" null,\n", | |
" React.createElement(\n", | |
" \"h1\",\n", | |
" null,\n", | |
" title\n", | |
" ),\n", | |
" React.createElement(Actions, { handler: handler, list: cache.chat_names }),\n", | |
" React.createElement(\n", | |
" \"div\",\n", | |
" { className: \"remarks\" },\n", | |
" React.createElement(\"div\", { className: \"remark\" })\n", | |
" )\n", | |
" );\n", | |
" })\n", | |
" });\n", | |
"});" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"execution_count": 20, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"%%jsx @out @2p\n", | |
"window.SecondPage = React.createClass({\n", | |
" render: function() {\n", | |
" let handler = (chat_id) => {\n", | |
" state.page = 3;\n", | |
" state.chat_id = chat_id;\n", | |
" get_users();\n", | |
" render();\n", | |
" }\n", | |
" let title = state.chat_names_get ?\n", | |
" 'Выберите чат для анализа' :\n", | |
" 'Идет получение списка чатов...';\n", | |
" return (\n", | |
" <div>\n", | |
" <h1>{title}</h1>\n", | |
" <Actions handler={handler} list={cache.chat_names}/>\n", | |
" <div className=\"remarks\">\n", | |
" <div className=\"remark\">\n", | |
" </div>\n", | |
" </div>\n", | |
" </div>\n", | |
" );\n", | |
" }\n", | |
"});" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 21, | |
"metadata": { | |
"collapsed": false, | |
"init_cell": true | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"application/javascript": [ | |
"\"use strict\";\n", | |
"\n", | |
"require([\"/static/react@15.3.1/build/react-dom.min.js\", \"/static/ramda@0.22.1/ramda.min.js\", \"jquery\", \"/static/snapsvg@0.4.1/dist/snap.svg-min.js\", \"react\", \"/static/visjs@4.16.1/dist/vis.min.js\", \"/static/d3@4.2.2/d3.min.js\"], function (ReactDOM, R, $, snap, React, vis, d3) {\n", | |
" window.ThirdPage = React.createClass({\n", | |
" displayName: \"ThirdPage\",\n", | |
"\n", | |
" render: function render() {\n", | |
" var title = 'Загрузка сообщений на сервер...';\n", | |
" if (state.page3 == 'finalized') {\n", | |
" title = 'Сообщения загружены!';\n", | |
" }\n", | |
" var preload = state.messages_get_offset / state.messages_count;\n", | |
" var progress = state.messages_post_offset / state.messages_count;\n", | |
" var count_text = '(' + state.messages_post_offset + ' / ' + state.messages_count + ')';\n", | |
" if (!state.messages_count) {\n", | |
" count_text = '';\n", | |
" }\n", | |
" var prog_text = {\n", | |
" get_users: 'Получение информации об участниках чата...',\n", | |
" post_users: 'Отправка информации об участниках чата...',\n", | |
" get_messages: 'Получение сообщений чата... ' + count_text,\n", | |
" post_messages: 'Отправка. сообщений чата... ' + count_text,\n", | |
" finalizing: 'Обработка данных...',\n", | |
" finalized: 'Завершение'\n", | |
" }[state.page3];\n", | |
" return React.createElement(\n", | |
" \"div\",\n", | |
" null,\n", | |
" React.createElement(\n", | |
" \"h1\",\n", | |
" null,\n", | |
" title\n", | |
" ),\n", | |
" React.createElement(Progress, { value: progress, preload: preload, text: prog_text }),\n", | |
" React.createElement(\n", | |
" \"div\",\n", | |
" { className: \"remarks\" },\n", | |
" React.createElement(\"div\", { className: \"remark\" })\n", | |
" )\n", | |
" );\n", | |
" }\n", | |
" });\n", | |
"});" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"execution_count": 21, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"%%jsx @out @3p\n", | |
"window.ThirdPage = React.createClass({\n", | |
" render: function() {\n", | |
" let title = 'Загрузка сообщений на сервер...';\n", | |
" if (state.page3 == 'finalized') {\n", | |
" title = 'Сообщения загружены!'\n", | |
" }\n", | |
" let preload = state.messages_get_offset / state.messages_count;\n", | |
" let progress = state.messages_post_offset / state.messages_count;\n", | |
" let count_text ='(' + state.messages_post_offset + ' / ' + state.messages_count + ')';\n", | |
" if (!state.messages_count) {\n", | |
" count_text = '';\n", | |
" }\n", | |
" let prog_text = {\n", | |
" get_users: 'Получение информации об участниках чата...',\n", | |
" post_users: 'Отправка информации об участниках чата...',\n", | |
" get_messages: 'Получение сообщений чата... ' + count_text,\n", | |
" post_messages: 'Отправка. сообщений чата... ' + count_text,\n", | |
" finalizing: 'Обработка данных...',\n", | |
" finalized: 'Завершение',\n", | |
" }[state.page3];\n", | |
" return (\n", | |
" <div>\n", | |
" <h1>{title}</h1>\n", | |
" <Progress value={progress} preload={preload} text={prog_text}/>\n", | |
" <div className=\"remarks\">\n", | |
" <div className=\"remark\">\n", | |
" </div>\n", | |
" </div> \n", | |
" </div>\n", | |
" )\n", | |
" }\n", | |
"});" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 22, | |
"metadata": { | |
"collapsed": false, | |
"init_cell": true | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"application/javascript": [ | |
"\"use strict\";\n", | |
"\n", | |
"require([\"/static/react@15.3.1/build/react-dom.min.js\", \"/static/ramda@0.22.1/ramda.min.js\", \"jquery\", \"/static/snapsvg@0.4.1/dist/snap.svg-min.js\", \"react\", \"/static/visjs@4.16.1/dist/vis.min.js\", \"/static/d3@4.2.2/d3.min.js\"], function (ReactDOM, R, $, snap, React, vis, d3) {\n", | |
" window.Application = React.createClass({\n", | |
" displayName: \"Application\",\n", | |
"\n", | |
" render: function render() {\n", | |
" var page_block = null;\n", | |
" if (state.page == 1) {\n", | |
" page_block = React.createElement(FirstPage, null);\n", | |
" } else if (state.page == 2) {\n", | |
" page_block = React.createElement(SecondPage, null);\n", | |
" } else if (state.page == 3) {\n", | |
" page_block = React.createElement(ThirdPage, null);\n", | |
" }\n", | |
" return React.createElement(\n", | |
" \"div\",\n", | |
" { className: \"container\" },\n", | |
" page_block\n", | |
" );\n", | |
" }\n", | |
" });\n", | |
"});" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"execution_count": 22, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"%%jsx @out @1a\n", | |
"window.Application = React.createClass({\n", | |
" render: function() {\n", | |
" let page_block = null;\n", | |
" if (state.page == 1) {\n", | |
" page_block = <FirstPage/>;\n", | |
" } else if (state.page == 2) {\n", | |
" page_block = <SecondPage/>;\n", | |
" } else if (state.page == 3) {\n", | |
" page_block = <ThirdPage/>;\n", | |
" }\n", | |
" return (\n", | |
" <div className=\"container\">\n", | |
" {page_block}\n", | |
" </div>\n", | |
" )\n", | |
" }\n", | |
"});" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 23, | |
"metadata": { | |
"collapsed": false, | |
"init_cell": true | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"application/javascript": [ | |
"\"use strict\";\n", | |
"\n", | |
"require([\"/static/react@15.3.1/build/react-dom.min.js\", \"/static/ramda@0.22.1/ramda.min.js\", \"jquery\", \"/static/snapsvg@0.4.1/dist/snap.svg-min.js\", \"react\", \"/static/visjs@4.16.1/dist/vis.min.js\", \"/static/d3@4.2.2/d3.min.js\"], function (ReactDOM, R, $, snap, React, vis, d3) {\n", | |
" window.render = function () {\n", | |
" ReactDOM.render(React.createElement(Application, null), document.getElementById('root'));\n", | |
" };\n", | |
"});" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"execution_count": 23, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"%%jsx @out @1r\n", | |
"window.render = function() {\n", | |
" ReactDOM.render(\n", | |
" <Application/>,\n", | |
" document.getElementById('root')\n", | |
" );\n", | |
"}" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false, | |
"init_cell": false | |
}, | |
"outputs": [], | |
"source": [ | |
"%%js no_out\n", | |
"reset();\n", | |
"render();" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 24, | |
"metadata": { | |
"collapsed": false, | |
"init_cell": true, | |
"scrolled": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div class=\"css1\">\n", | |
" <div id=\"root\" class=\"root\"></div>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
"<IPython.core.display.HTML object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"%%html @body\n", | |
"<div class=\"css1\">\n", | |
" <div id=\"root\" class=\"root\"></div>\n", | |
"</div>" | |
] | |
}, | |
{ | |
"cell_type": "raw", | |
"metadata": {}, | |
"source": [ | |
"https://oauth.vk.com/blank.html#access_token=ed45541790cfd162f31da5b99f17fee31e40fb0f22ff483ef3159ae26e0794aec70e7003c2a461287506f&expires_in=86400&user_id=12518218" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "py3", | |
"language": "python", | |
"name": "py3" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 3 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython3", | |
"version": "3.5.2" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 1 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment