<!DOCTYPE html> <html> <head> <title>AIL Framework</title> <link rel="icon" href="{{ url_for('static', filename='image/ail-icon.png') }}"> <!-- Core CSS --> <link href="{{ url_for('static', filename='css/bootstrap4.min.css') }}" rel="stylesheet"> <link href="{{ url_for('static', filename='css/font-awesome.min.css') }}" rel="stylesheet"> <!-- JS --> <script src="{{ url_for('static', filename='js/jquery.js')}}"></script> <script src="{{ url_for('static', filename='js/helper.js')}}"></script> <script src="{{ url_for('static', filename='js/popper.min.js')}}"></script> <script src="{{ url_for('static', filename='js/echarts.min.js')}}"></script> <script src="{{ url_for('static', filename='js/bootstrap4.min.js')}}"></script> <style> .popover { max-width: none; width: 500px; } .icon-button { position: relative; display: inline-block; border: none; background: none; {#padding: 0;#} margin: 0; cursor: pointer; outline: inherit; transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out; } .icon-wrapper { position: relative; display: inline-block; } .notification-badge { position: absolute; top: -10px; right: -10px; font-size: 14px; background: forestgreen; } </style> </head> <body> {% include 'nav_bar.html' %} <div class="container-fluid"> <div class="row"> <div class="col-12 col-xl-6"> <div id="feeders_dashboard" style="width: 100%; height:600px;"></div> <div class="card mt-1 mb-4"> <div class="card-header text-white bg-dark"> <div class="row"> <div class="col-1"> <i class="fas fa-user-secret fa-2x"></i> </div> <div class="col-5"> <div class="row"> <div class="col-6"> <div> <a href="{{ url_for('crawler_splash.domains_search_today') }}?type=onion&up=True" class="badge badge-success" id="stat_crawler_onion_domain_up">{{ crawlers_stats['onion']['up'] }}</a> Up </div> <div> <a href="{{ url_for('crawler_splash.domains_search_today') }}?type=onion&down=True" class="badge badge-danger" id="stat_crawler_onion_domain_down">{{ crawlers_stats['onion']['down'] }}</a> Down </div> </div> <div class="col-6"> <div> <a href="{{ url_for('crawler_splash.domains_search_today') }}?type=onion&up=True&down=True" class="badge badge-success" id="stat_crawler_onion_total">{{ crawlers_stats['onion']['crawled'] }}</a> Crawled </div> <div> <span class="badge badge-warning" id="stat_crawler_onion_queue">{{ crawlers_stats['onion']['queue'] }}</span> Queue </div> </div> </div> </div> <div class="col-1"> <i class="fab fa-html5 fa-2x"></i> </div> <div class="col-5"> <div class="row"> <div class="col-6"> <div> <a href="{{ url_for('crawler_splash.domains_search_today') }}?type=web&up=True" class="badge badge-success" id="stat_crawler_regular_domain_up">{{ crawlers_stats['web']['up'] }}</a> UP </div> <div> <a href="{{ url_for('crawler_splash.domains_search_today') }}?type=web&down=True" class="badge badge-danger" id="stat_crawler_regular_domain_down">{{ crawlers_stats['web']['down'] }}</a> DOWN </div> </div> <div class="col-6"> <div> <a href="{{ url_for('crawler_splash.domains_search_today') }}?type=web&up=True&down=True" class="badge badge-success" id="stat_crawler_regular_total">{{ crawlers_stats['web']['crawled'] }}</a> Crawled </div> <div> <span class="badge badge-warning" id="stat_crawler_regular_queue">{{ crawlers_stats['web']['queue'] }}</span> Queue </div> </div> </div> </div> </div> </div> </div> </div> <div class="col-12 col-xl-6"> <h3 class="text-center mt-1 mb-4" id="current_date"></h3> <div class="row"> {% for obj_type in nb_objects %} <div class="col-sm-6 col-md-4 col-lg-3 text-center mb-4"> {% with type=obj_type, name=nb_objects[obj_type]['name'], icon=nb_objects[obj_type]['icon']['icon'], nb=nb_objects[obj_type]['nb'], url=nb_objects[obj_type]['link'] %} {% include 'objects/block_obj_button.html' %} {% endwith %} </div> {% endfor %} </div> </div> </div> <div class="row"> <div class="col-12 col-xl-6"> <table class="table"> <thead> <tr> <th><i class="fa-solid fa-crosshairs"></i></th> <th>tracker</th> <th class="text-center"><i class="fas fa-cube"></i></th> <th>Time</th> </tr> </thead> <tbody id="tracked_objs"> {% for tracker in trackers %} <tr> <td>{{ tracker['type'] }}</td> <td style="word-break: break-all;"> <a href="{{ url_for('hunters.show_tracker') }}?uuid={{ tracker['uuid'] }}">{% if tracker['description'] %}{{ tracker['description'] }}{% else %}{{ tracker['tracked'] }}{% endif %}</a> </td> <td class="text-center"> <a href="{{ tracker['obj']['link'] }}" onmouseenter="show_obj_tooltip(this, '{{ tracker['obj']['gid'] }}')" onmouseleave="hide_obj_tooltip(this)"> <svg height="26" width="26" style="pointer-events:none;"> <g class="nodes"> <circle cx="13" cy="13" r="13" fill="{{ tracker['obj']['icon']['color'] }}"></circle> <text x="13" y="13" text-anchor="middle" dominant-baseline="central" class="{{ tracker['obj']['icon']['style'] }}" font-size="16px">{{ tracker['obj']['icon']['icon'] }}</text> </g> </svg> </a> </td> <td>{{ tracker['timestamp'] }}</td> </tr> {% endfor %} </tbody> </table> </div> <div class="col-12 col-xl-6"> <table class="table"> <thead> <tr> <th class="text-center"><i class="fas fa-cube"></i></th> <th>ID</th> <th><i class="fas fa-tag"></i> Tags</th> <th>Time</th> </tr> </thead> <tbody id="t_tags_objs"> {% for t_obj in tagged_objs %} <tr> <td> <a href="{{ t_obj['link'] }}" onmouseenter="show_obj_tooltip(this, '{{ t_obj['gid'] }}')" onmouseleave="hide_obj_tooltip(this)"> <svg height="26" width="26"> <g class="nodes"> <circle cx="13" cy="13" r="13" fill="{{ t_obj['icon']['color'] }}"></circle> <text x="13" y="13" text-anchor="middle" dominant-baseline="central" class="{{ t_obj['icon']['style'] }}" font-size="16px">{{ t_obj['icon']['icon'] }}</text> </g> </svg> </a> </td> <td style="word-break: break-all;"> <a href="{{ t_obj['link'] }}">{{ t_obj['id'] }}</a> </td> <td> {% for tag in t_obj['tags'] %} <span class="badge badge-{{ bootstrap_label[loop.index0 % 5] }}">{{ tag }}</span> {% endfor %} </td> <td>{{ t_obj['date_tag'] }}</td> </tr> {% endfor %} </tbody> </table> </div> </div> </div> <script> var chart = {}; $(document).ready(function(){ $("#page-Dashboard").addClass("active"); $("#nav_dashboard_{{obj_type}}").addClass("active"); updateDate(); }); var btn_selector = { {% for obj_type in nb_objects %} '{{ obj_type }}': $("#obj_btn_{{ obj_type }}"), {% endfor %} } </script> <script> var tags_colors = ['primary', 'success', 'danger', 'warning', 'info']; var url_obj_description = "{{ url_for('correlation.get_description') }}?object_id="; // Init Dashboard var feederChart = echarts.init(document.getElementById('feeders_dashboard')); window.addEventListener('resize', function() { feederChart.resize(); }); var optionFeeder; var maxDataLength = 21; var feeders_names = [{% for feeder in feeders_dashboard['data'] %}'{{ feeder }}', {% endfor %}] var feeders_xaxis = [{% for date in feeders_dashboard['dates'] %}'{{ date }}', {% endfor %}] var feeders_data = { {% for feeder in feeders_dashboard['data'] %} '{{ feeder }}': {{ feeders_dashboard['data'][feeder] }}, {% endfor %} } optionFeeder = { title: { text: 'Feeders' }, tooltip: { trigger: 'axis', axisPointer: { type: 'cross', label: { backgroundColor: '#6a7985' } } }, legend: { data: feeders_names }, grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true }, xAxis: [ { type: 'category', boundaryGap: false, data: feeders_xaxis } ], yAxis: [ { type: 'value' } ], series: [ {% for feeder in feeders_dashboard['data'] %} { name: '{{ feeder }}', type: 'line', stack: 'Total', areaStyle: {}, emphasis: { focus: 'series' }, data: feeders_data['{{ feeder }}'] }, {% endfor %} ] }; optionFeeder && feederChart.setOption(optionFeeder); {# TODO UPDATE NEW FEEDER NAME#} function updateFeederChart(data) { let new_date = data['date'] feeders_xaxis.push(new_date) feeders_xaxis.shift() for (const f_name in data['data']) { if (f_name in feeders_data) { feeders_data[f_name].push(data['data'][f_name]) feeders_data[f_name].shift() } else { let fdata = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, data['data'][f_name]] feeders_names.push(f_name) feeders_data[f_name] = fdata // add new feeder optionFeeder.legend.data.push(f_name) optionFeeder.series.push({name: f_name, type: 'line', stack: 'Total', areaStyle: {}, emphasis: {focus: 'series'}, data: feeders_data[f_name]}) } } feederChart.setOption(optionFeeder) } function updateDate() { let d = new Date(); let day = d.getUTCDate(); if (day < 10) { day = "0" + day; } let current_date = d.getUTCFullYear() + ' - ' + (d.getUTCMonth() + 1) + ' - ' + day; $('#current_date').text(current_date) } function updateNbObjects(data) { for (const obj_type in data) { btn_selector[obj_type].text(data[obj_type]); } } function updateCrawlerStats(data) { updateDate(); $("#stat_crawler_onion_domain_up").text(data['onion']['up']); $("#stat_crawler_onion_domain_down").text(data['onion']['down']); $("#stat_crawler_onion_total").text(data['onion']['crawled']); $("#stat_crawler_onion_queue").text(data['onion']['queue']); $("#stat_crawler_regular_domain_up").text(data['web']['up']); $("#stat_crawler_regular_domain_down").text(data['web']['down']); $("#stat_crawler_regular_total").text(data['web']['crawled']); $("#stat_crawler_regular_queue").text(data['web']['queue']); } /////// function create_obj_svg(container, obj_gid, url, color, fa_style, icon) { var svg_obj = '<svg height="26" width="26"> <g class="nodes"> <circle cx="13" cy="13" r="13" fill="' + color + '"></circle> <text x="13" y="13" text-anchor="middle" dominant-baseline="central" class="' + fa_style + '" font-size="16px">' + icon + '</text> </g> </svg>'; var obj_link = $('<a>'); obj_link.on('mouseenter', function () { show_obj_tooltip(this, obj_gid); }); obj_link.on('mouseleave', function () { hide_obj_tooltip(this); }); obj_link.attr('href', url); obj_link.html(svg_obj); container.append(obj_link); return container } function create_tags_badges(container, tags) { var tspan = ''; for (const i in tags) { tspan = tspan + '<span class="badge badge-' + 'primary' + '">' + sanitize_text(tags[i]) + '</span>' } return tspan; } function update_tags_obj_dashboard(data) { // delete table var tbody = $("#t_tags_objs"); var ntd; tbody.empty(); for (const elem in data) { let obj = data[elem]; var row = $('<tr></tr>'); ntd = $('<td></td>'); row.append(create_obj_svg(ntd, obj['gid'], obj.link, obj['icon']['color'], obj['icon']['style'], obj['icon']['icon'])) row.append('<td style="word-break: break-all;"><a href="'+ obj['link'] + '">' + sanitize_text(obj['id']) + '</a></td>'); ntd = $('<td></td>'); row.append(create_tags_badges(ntd, obj['tags'])); row.append('<td>' + obj['date_tag'] + '</td>'); tbody.append(row); {# {% for tag in t_obj['tags'] %}#} {# <span class="badge badge-{{ bootstrap_label[loop.index0 % 5] }}">{{ tag }}</span>#} {# {% endfor %}#} {#</td>#} } } function update_tracked_objs_dashboard(data) { // delete table var tbody = $("#tracked_objs"); var ntd; tbody.empty(); for (const elem in data) { let tracker = data[elem]; var row = $('<tr></tr>'); row.append('<td>' + tracker['type'] + '</td>'); let name; if (tracker['description']) { name = tracker['description']; } else { name = tracker['tracked']; } row.append('<td style="word-break: break-all;"><a href="{{ url_for('hunters.show_tracker') }}?uuid=' + tracker['uuid'] + '">' + sanitize_text(name) + '</a></td>'); ntd = $('<td class="text-center"></td>'); row.append(create_obj_svg(ntd, tracker['obj']['gid'], tracker['obj']['link'], tracker['obj']['icon']['color'], tracker['obj']['icon']['style'], tracker['obj']['icon']['icon'])); row.append('<td>' + tracker['timestamp'] + '</td>'); tbody.append(row); } } // WebSocket var socket = new WebSocket("wss://" + window.location.host + "/ws/dashboard"); socket.wsocket = function(event) { console.log("WebSocket connection opened:", event); }; socket.onmessage = function(event) { $("[data-toggle='popover']").popover('destroy'); let data = JSON.parse(event.data); updateFeederChart(data['feeders']); updateNbObjects(data['objs']); updateCrawlerStats(data['crawler']); update_tracked_objs_dashboard(data['trackers']); update_tags_obj_dashboard(data['tags']); }; socket.onerror = function(error) { console.error('WebSocket error:', error); }; socket.onclose = function(event) { console.log('WebSocket connection closed:', event); }; </script> </body> </html>