ZahirJS commited on
Commit
248b059
·
verified ·
1 Parent(s): f75bb7b

Create network_graph_generator.py

Browse files
Files changed (1) hide show
  1. network_graph_generator.py +118 -0
network_graph_generator.py ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import graphviz
2
+ import json
3
+ from tempfile import NamedTemporaryFile
4
+ import os
5
+
6
+ def generate_network_graph(json_input: str, output_format: str) -> str:
7
+ try:
8
+ if not json_input.strip():
9
+ return "Error: Empty input"
10
+
11
+ data = json.loads(json_input)
12
+
13
+ if 'nodes' not in data or 'connections' not in data:
14
+ raise ValueError("Missing required fields: nodes or connections")
15
+
16
+ dot = graphviz.Graph(
17
+ name='NetworkGraph',
18
+ format='png',
19
+ engine='neato',
20
+ graph_attr={
21
+ 'overlap': 'false',
22
+ 'splines': 'true',
23
+ 'bgcolor': 'white',
24
+ 'pad': '0.5',
25
+ 'layout': 'neato'
26
+ },
27
+ node_attr={
28
+ 'fixedsize': 'false'
29
+ }
30
+ )
31
+
32
+ base_color = '#19191a'
33
+ lightening_factor = 0.12
34
+
35
+ nodes = data.get('nodes', [])
36
+ connections = data.get('connections', [])
37
+
38
+ for i, node in enumerate(nodes):
39
+ node_id = node.get('id')
40
+ label = node.get('label')
41
+ node_type = node.get('type', 'default')
42
+
43
+ if not all([node_id, label]):
44
+ raise ValueError(f"Invalid node: {node}")
45
+
46
+ current_depth = node.get('depth', i % 5)
47
+
48
+ if not isinstance(base_color, str) or not base_color.startswith('#') or len(base_color) != 7:
49
+ base_color_safe = '#19191a'
50
+ else:
51
+ base_color_safe = base_color
52
+
53
+ base_r = int(base_color_safe[1:3], 16)
54
+ base_g = int(base_color_safe[3:5], 16)
55
+ base_b = int(base_color_safe[5:7], 16)
56
+
57
+ current_r = base_r + int((255 - base_r) * current_depth * lightening_factor)
58
+ current_g = base_g + int((255 - base_g) * current_depth * lightening_factor)
59
+ current_b = base_b + int((255 - base_b) * current_depth * lightening_factor)
60
+
61
+ current_r = min(255, current_r)
62
+ current_g = min(255, current_g)
63
+ current_b = min(255, current_b)
64
+
65
+ node_color = f'#{current_r:02x}{current_g:02x}{current_b:02x}'
66
+ font_color = 'white' if current_depth * lightening_factor < 0.6 else 'black'
67
+ font_size = max(9, 14 - (current_depth * 1))
68
+
69
+ if node_type == 'server':
70
+ shape = 'box'
71
+ elif node_type == 'database':
72
+ shape = 'cylinder'
73
+ elif node_type == 'user':
74
+ shape = 'ellipse'
75
+ elif node_type == 'service':
76
+ shape = 'hexagon'
77
+ else:
78
+ shape = 'circle'
79
+
80
+ dot.node(
81
+ node_id,
82
+ label,
83
+ shape=shape,
84
+ style='filled',
85
+ fillcolor=node_color,
86
+ fontcolor=font_color,
87
+ fontsize=str(font_size)
88
+ )
89
+
90
+ for connection in connections:
91
+ from_node = connection.get('from')
92
+ to_node = connection.get('to')
93
+ label = connection.get('label', '')
94
+ weight = connection.get('weight', 1)
95
+
96
+ if not all([from_node, to_node]):
97
+ raise ValueError(f"Invalid connection: {connection}")
98
+
99
+ penwidth = str(max(1, min(5, weight)))
100
+
101
+ dot.edge(
102
+ from_node,
103
+ to_node,
104
+ label=label,
105
+ color='#4a4a4a',
106
+ fontcolor='#4a4a4a',
107
+ fontsize='10',
108
+ penwidth=penwidth
109
+ )
110
+
111
+ with NamedTemporaryFile(delete=False, suffix=f'.{output_format}') as tmp:
112
+ dot.render(tmp.name, format=output_format, cleanup=True)
113
+ return f"{tmp.name}.{output_format}"
114
+
115
+ except json.JSONDecodeError:
116
+ return "Error: Invalid JSON format"
117
+ except Exception as e:
118
+ return f"Error: {str(e)}"