|
@@ -0,0 +1,158 @@
|
|
|
+<!DOCTYPE html>
|
|
|
+<html lang="en">
|
|
|
+ <head>
|
|
|
+ <title>Network</title>
|
|
|
+ <script type="text/javascript" src="vis-network.min.js"></script>
|
|
|
+ <style>
|
|
|
+ html, body {
|
|
|
+ height: 100%;
|
|
|
+ overflow: hidden;
|
|
|
+ }
|
|
|
+ /* Define the styles for the network container */
|
|
|
+ #network {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ }
|
|
|
+ </style>
|
|
|
+ </head>
|
|
|
+ <body>
|
|
|
+ <div id="network"></div>
|
|
|
+ <script type="text/javascript">
|
|
|
+ const servers = {
|
|
|
+ 'machteburch.social': {
|
|
|
+ domain: 'machteburch.social',
|
|
|
+ accountCount: undefined,
|
|
|
+ botCount: undefined,
|
|
|
+ peers: undefined
|
|
|
+ },
|
|
|
+ };
|
|
|
+
|
|
|
+ // Create nodes and edges for the network
|
|
|
+ const nodes = new vis.DataSet([]);
|
|
|
+ const edges = new vis.DataSet([]);
|
|
|
+
|
|
|
+ // Initialize the network
|
|
|
+ const container = document.getElementById('network');
|
|
|
+ const data = {
|
|
|
+ nodes,
|
|
|
+ edges,
|
|
|
+ };
|
|
|
+
|
|
|
+ const options = {
|
|
|
+ nodes: {
|
|
|
+ color: {
|
|
|
+ background: 'white',
|
|
|
+ border: 'black',
|
|
|
+ },
|
|
|
+ },
|
|
|
+ };
|
|
|
+
|
|
|
+ const network = new vis.Network(container, data, options);
|
|
|
+ network.on("selectNode", function (params) {
|
|
|
+ if (params.nodes.length === 1) {
|
|
|
+ var node = nodes.get(params.nodes[0]);
|
|
|
+ window.open(`https://${params.nodes[0]}`, '_blank');
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+
|
|
|
+ async function fetchDataFromDirectory(domain, origin) {
|
|
|
+ if(servers[domain] && servers[domain].accountCount != undefined)
|
|
|
+ return;
|
|
|
+ const server = {
|
|
|
+ domain: domain,
|
|
|
+ accountCount: 0,
|
|
|
+ botCount: 0,
|
|
|
+ peers: []
|
|
|
+ }
|
|
|
+ servers[domain] = server
|
|
|
+ try {
|
|
|
+ const response = await fetch(`https://${domain}/api/v1/directory`);
|
|
|
+ if (response.ok) {
|
|
|
+ const directoryData = await response.json();
|
|
|
+ // Process directoryData and determine the percentage of bot accounts
|
|
|
+ server.botCount = directoryData.filter(account => account.bot).length;
|
|
|
+ server.accountCount = directoryData.length;
|
|
|
+ // Determine the node color based on the percentage of bot accounts
|
|
|
+ const color = determineNodeColor(server.botCount / server.accountCount);
|
|
|
+
|
|
|
+ // Update the node with the new information
|
|
|
+ const updatedNodes = [{
|
|
|
+ id: server.domain,
|
|
|
+ label: `${server.domain}\n Bots: ${server.botCount}/${server.accountCount}`,
|
|
|
+ value: server.botCount / server.accountCount * 100,
|
|
|
+ color: server.accountCount > 0 ? color : undefined,
|
|
|
+ }];
|
|
|
+ if(!nodes.get(origin))
|
|
|
+ updatedNodes.push({
|
|
|
+ id: origin,
|
|
|
+ label: origin,
|
|
|
+ })
|
|
|
+ nodes.update(updatedNodes);
|
|
|
+ const newEdge = {
|
|
|
+ from: origin,
|
|
|
+ to: domain,
|
|
|
+ };
|
|
|
+ edges.add(newEdge);
|
|
|
+ return
|
|
|
+ } else {
|
|
|
+ console.error('Failed to fetch data from the directory');
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('An error occurred:', error);
|
|
|
+ }
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // Function to determine the node color based on the bot percentage
|
|
|
+ function determineNodeColor(percentage) {
|
|
|
+ // Implement a logic to determine the color based on the bot percentage
|
|
|
+ const hue = 120 - percentage * 120;
|
|
|
+ return `hsl(${hue}, 100%, 80%)`;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Function to fetch peers data from server
|
|
|
+ async function fetchPeers(server) {
|
|
|
+ const domain = server.domain
|
|
|
+ server.peers = [];
|
|
|
+ try {
|
|
|
+ const response = await fetch(`https://${domain}/api/v1/instance/peers`);
|
|
|
+ if (response.ok) {
|
|
|
+ server.peers = await response.json();
|
|
|
+ } else {
|
|
|
+ console.error(`Failed to fetch data from peer domain: ${domain}`);
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error(`An error occurred while fetching data from peer domain: ${domain}`, error);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ async function queryPeer(server, domain) {
|
|
|
+ if(!servers[domain]) {
|
|
|
+ await fetchDataFromDirectory(domain, server.domain)
|
|
|
+ await fetchPeers(servers[domain])
|
|
|
+ }
|
|
|
+ }
|
|
|
+ async function start() {
|
|
|
+ for (const domain in servers) {
|
|
|
+ await fetchDataFromDirectory(domain)
|
|
|
+ await fetchPeers(servers[domain])
|
|
|
+ }
|
|
|
+ let hasWork = true
|
|
|
+ while(hasWork) {
|
|
|
+ hasWork = false
|
|
|
+ for(const domain in servers) {
|
|
|
+ const server = servers[domain]
|
|
|
+ const unseenPeers = server.peers.filter(peerDomain => !servers[peerDomain])
|
|
|
+ for(const peerDomain of unseenPeers.slice(0, 20)) {
|
|
|
+ hasWork = true
|
|
|
+ queryPeer(server, peerDomain)
|
|
|
+ await new Promise(resolve => setTimeout(resolve, 20));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ start()
|
|
|
+ </script>
|
|
|
+ </body>
|
|
|
+</html>
|