summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author@syxhe <t.me/syxhe>2025-10-02 16:21:29 -0500
committer@syxhe <t.me/syxhe>2025-10-02 16:21:29 -0500
commit82c6f12de286db3c89758f201f619a63accf17f4 (patch)
treee32704f431c3c474fffcd94a227ecfcb40058922
parent267b35a813dd1ad5c3eec253f5d6f9d613bbb1ec (diff)
Begin the over-engineering process
-rw-r--r--.gitmodules3
-rw-r--r--.idea/codeStyles/codeStyleConfig.xml5
-rw-r--r--README.md26
-rwxr-xr-xbuild.bash31
-rw-r--r--src/main/java/ChannelNode.java89
-rw-r--r--src/main/java/IChannelNode.java23
m---------td0
7 files changed, 129 insertions, 48 deletions
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..b641dcc
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
1[submodule "td"]
2 path = td
3 url = https://github.com/tdlib/td
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..a55e7a1
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
1<component name="ProjectCodeStyleConfiguration">
2 <state>
3 <option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
4 </state>
5</component> \ No newline at end of file
diff --git a/README.md b/README.md
index 61b4229..a592f5f 100644
--- a/README.md
+++ b/README.md
@@ -2,4 +2,28 @@
2 2
3## Map the connections between Telegram channels using TDLib 3## Map the connections between Telegram channels using TDLib
4 4
5TG Mapper is a tool for satiating my curiosity. For a long time, I've wanted to see how interconnected different TG channels are, and this is my solution. TG Mapper uses TDLib to search through channel posts, find forwarded posts, and store connections in a graph \ No newline at end of file 5TG Mapper is a tool for satiating my curiosity. For a long time, I've wanted to see how interconnected different TG channels are, and this is my solution. TG Mapper uses TDLib to search through channel posts, find forwarded posts, and store connections in a graph
6
7## USAGE
8
9## DEPENDENCIES
10
11## BUILDING
12
13Clone repo & submodules:
14
15```bash
16git clone --recurse-submodules https://git.dabikers.online/tgmapper
17```
18
19Move into dir and run build script
20
21```bash
22./build.bash
23```
24
25This will output a .jar. Now, run the jar
26
27```bash
28java run -jar tgmapper.jar
29``` \ No newline at end of file
diff --git a/build.bash b/build.bash
new file mode 100755
index 0000000..f2b188d
--- /dev/null
+++ b/build.bash
@@ -0,0 +1,31 @@
1#!/usr/bin/env -vS bash
2
3SOMEWHAT_REAL_DIR="$(realpath "$0")"
4FILENAME="${SOMEWHAT_REAL_DIR##*/}"
5PATH_TO="${SOMEWHAT_REAL_DIR/$FILENAME/}"
6
7function runInLocal() {
8 if [[ "$(pwd)/" != "$PATH_TO" ]]; then
9 (cd "$PATH_TO" && bash "$FILENAME")
10 exit $?
11 fi
12
13 return 0
14}
15
16function buildTDLIB() {
17
18
19 return 0
20}
21
22function buildJar() {
23
24 return 0
25}
26
27runInLocal && \
28 buildTDLIB && \
29 buildJar
30
31exit "$?"
diff --git a/src/main/java/ChannelNode.java b/src/main/java/ChannelNode.java
index ddc1488..20a7ac0 100644
--- a/src/main/java/ChannelNode.java
+++ b/src/main/java/ChannelNode.java
@@ -1,7 +1,6 @@
1import java.util.ArrayList; 1import java.util.*;
2import java.util.List; 2import java.util.concurrent.atomic.AtomicInteger;
3import java.util.Map; 3import static java.util.Map.entry;
4import java.util.TreeMap;
5 4
6public class ChannelNode implements IChannelNode { 5public class ChannelNode implements IChannelNode {
7 private Map<IChannelNode, Integer> incoming; 6 private Map<IChannelNode, Integer> incoming;
@@ -18,9 +17,10 @@ public class ChannelNode implements IChannelNode {
18 if(dir == null) throw new IllegalArgumentException("direction is null"); 17 if(dir == null) throw new IllegalArgumentException("direction is null");
19 if(conmap.containsKey(this)) throw new IllegalArgumentException("connection map contains this node"); 18 if(conmap.containsKey(this)) throw new IllegalArgumentException("connection map contains this node");
20 19
21 int dv = dir.getVal(); 20 Direction.overVals(Map.ofEntries(
22 if(dv >= Direction.INCOMING.getVal()) incoming = conmap; 21 entry(Direction.INCOMING, () -> incoming = conmap),
23 if(dv >= Direction.OUTGOING.getVal()) outgoing = conmap; 22 entry(Direction.OUTGOING, () -> outgoing = conmap)
23 ), dir);
24 } 24 }
25 25
26 @Override 26 @Override
@@ -30,9 +30,10 @@ public class ChannelNode implements IChannelNode {
30 if(dir == null) throw new IllegalArgumentException("dir is null"); 30 if(dir == null) throw new IllegalArgumentException("dir is null");
31 if(num < 0) throw new IllegalArgumentException("num < 0"); 31 if(num < 0) throw new IllegalArgumentException("num < 0");
32 32
33 int dv = dir.getVal(); 33 Direction.overVals(Map.ofEntries(
34 if(dv >= Direction.INCOMING.getVal()) incoming.put(node, num); 34 entry(Direction.INCOMING, () -> incoming.put(node, num)),
35 if(dv >= Direction.OUTGOING.getVal()) outgoing.put(node, num); 35 entry(Direction.OUTGOING, () -> outgoing.put(node, num))
36 ), dir);
36 } 37 }
37 38
38 @Override 39 @Override
@@ -41,9 +42,10 @@ public class ChannelNode implements IChannelNode {
41 if(node == this) throw new IllegalArgumentException("node is self"); 42 if(node == this) throw new IllegalArgumentException("node is self");
42 if(dir == null) throw new IllegalArgumentException("dir is null"); 43 if(dir == null) throw new IllegalArgumentException("dir is null");
43 44
44 int dv = dir.getVal(); 45 Direction.overVals(Map.ofEntries(
45 if(dv >= Direction.INCOMING.getVal()) incoming.put(node, incoming.get(node) + 1); 46 entry(Direction.INCOMING, () -> incoming.put(node, incoming.get(node) + 1)),
46 if(dv >= Direction.OUTGOING.getVal()) outgoing.put(node, outgoing.get(node) + 1); 47 entry(Direction.OUTGOING, () -> outgoing.put(node, outgoing.get(node) + 1))
48 ), dir);
47 } 49 }
48 50
49 @Override 51 @Override
@@ -52,14 +54,12 @@ public class ChannelNode implements IChannelNode {
52 if(dir == null) throw new IllegalArgumentException("dir is null"); 54 if(dir == null) throw new IllegalArgumentException("dir is null");
53 nodes.forEach((node) -> {if(node == this) throw new IllegalArgumentException("one of the included nodes is this node");}); 55 nodes.forEach((node) -> {if(node == this) throw new IllegalArgumentException("one of the included nodes is this node");});
54 56
55 int dv = dir.getVal(), 57 for(IChannelNode node: nodes) {
56 incomingV = Direction.INCOMING.getVal(), 58 Direction.overVals(Map.ofEntries(
57 outgoingV = Direction.OUTGOING.getVal(); 59 entry(Direction.INCOMING, () -> incoming.put(node, incoming.get(node) + 1)),
58 60 entry(Direction.OUTGOING, () -> outgoing.put(node, outgoing.get(node) + 1))
59 nodes.forEach((node) -> { 61 ), dir);
60 if(dv >= incomingV) incoming.put(node, incoming.get(node) + 1); 62 }
61 if(dv >= outgoingV) outgoing.put(node, outgoing.get(node) + 1);
62 });
63 } 63 }
64 64
65 @Override 65 @Override
@@ -68,9 +68,10 @@ public class ChannelNode implements IChannelNode {
68 if(node == this) throw new IllegalArgumentException("node is self"); 68 if(node == this) throw new IllegalArgumentException("node is self");
69 if(dir == null) throw new IllegalArgumentException("dir is null"); 69 if(dir == null) throw new IllegalArgumentException("dir is null");
70 70
71 int dv = dir.getVal(); 71 Direction.overVals(Map.ofEntries(
72 if(dv >= Direction.INCOMING.getVal()) incoming.put(node, Math.max(incoming.get(node) - 1, 0)); 72 entry(Direction.INCOMING, () -> incoming.put(node, Math.max(incoming.get(node) - 1, 0))),
73 if(dv >= Direction.OUTGOING.getVal()) outgoing.put(node, Math.max(outgoing.get(node) - 1, 0)); 73 entry(Direction.OUTGOING, () -> outgoing.put(node, Math.max(outgoing.get(node) - 1, 0)))
74 ), dir);
74 } 75 }
75 76
76 @Override 77 @Override
@@ -79,23 +80,22 @@ public class ChannelNode implements IChannelNode {
79 if(dir == null) throw new IllegalArgumentException("dir is null"); 80 if(dir == null) throw new IllegalArgumentException("dir is null");
80 nodes.forEach((node) -> {if(node == this) throw new IllegalArgumentException("one of the included nodes is this node");}); 81 nodes.forEach((node) -> {if(node == this) throw new IllegalArgumentException("one of the included nodes is this node");});
81 82
82 int dv = dir.getVal(), 83 for(IChannelNode node: nodes) {
83 incomingV = Direction.INCOMING.getVal(), 84 Direction.overVals(Map.ofEntries(
84 outgoingV = Direction.OUTGOING.getVal(); 85 entry(Direction.INCOMING, () -> incoming.put(node, Math.max(incoming.get(node) - 1, 0))),
85 86 entry(Direction.OUTGOING, () -> outgoing.put(node, Math.max(outgoing.get(node) - 1, 0)))
86 nodes.forEach((node) -> { 87 ), dir);
87 if(dv >= incomingV) incoming.put(node, Math.max(incoming.get(node) - 1, 0)); 88 }
88 if(dv >= outgoingV) outgoing.put(node, Math.max(outgoing.get(node) - 1, 0));
89 });
90 } 89 }
91 90
92 @Override 91 @Override
93 public void clearConnections(Direction dir) throws IllegalArgumentException { 92 public void clearConnections(Direction dir) throws IllegalArgumentException {
94 if(dir == null) throw new IllegalArgumentException("dir is null"); 93 if(dir == null) throw new IllegalArgumentException("dir is null");
95 94
96 int dv = dir.getVal(); 95 Direction.overVals(Map.ofEntries(
97 if(dv >= Direction.INCOMING.getVal()) incoming.clear(); 96 entry(Direction.INCOMING, () -> incoming.clear()),
98 if(dv >= Direction.OUTGOING.getVal()) outgoing.clear(); 97 entry(Direction.OUTGOING, () -> outgoing.clear())
98 ), dir);
99 } 99 }
100 100
101 @Override 101 @Override
@@ -115,12 +115,12 @@ public class ChannelNode implements IChannelNode {
115 public int getNumConnections(Direction dir) throws IllegalArgumentException { 115 public int getNumConnections(Direction dir) throws IllegalArgumentException {
116 if(dir == null) throw new IllegalArgumentException("dir is null"); 116 if(dir == null) throw new IllegalArgumentException("dir is null");
117 117
118 int total = 0; 118 AtomicInteger total = new AtomicInteger();
119 int dv = dir.getVal(); 119 Direction.overVals(Map.ofEntries(
120 120 entry(Direction.INCOMING, () -> {for(int i: incoming.values()) total.addAndGet(i);}),
121 if(dv >= Direction.INCOMING.getVal()) for(int i: incoming.values()) total += i; 121 entry(Direction.OUTGOING, () -> {for(int i: outgoing.values()) total.addAndGet(i);})
122 if(dv >= Direction.OUTGOING.getVal()) for(int i: outgoing.values()) total += i; 122 ), dir);
123 return total; 123 return total.get();
124 } 124 }
125 125
126 @Override 126 @Override
@@ -137,10 +137,11 @@ public class ChannelNode implements IChannelNode {
137 public List<Map<IChannelNode, Integer>> getConnections(Direction dir) throws IllegalArgumentException { 137 public List<Map<IChannelNode, Integer>> getConnections(Direction dir) throws IllegalArgumentException {
138 if(dir == null) throw new IllegalArgumentException("dir is null"); 138 if(dir == null) throw new IllegalArgumentException("dir is null");
139 139
140 int dv = dir.getVal();
141 ArrayList<Map<IChannelNode, Integer>> res = new ArrayList<>(); 140 ArrayList<Map<IChannelNode, Integer>> res = new ArrayList<>();
142 if(dv >= Direction.INCOMING.getVal()) res.add(incoming); 141 Direction.overVals(Map.ofEntries(
143 if(dv >= Direction.OUTGOING.getVal()) res.add(outgoing); 142 entry(Direction.INCOMING, () -> res.add(incoming)),
143 entry(Direction.OUTGOING, () -> res.add(outgoing))
144 ), dir);
144 145
145 return res; 146 return res;
146 } 147 }
diff --git a/src/main/java/IChannelNode.java b/src/main/java/IChannelNode.java
index baf7572..a6446f1 100644
--- a/src/main/java/IChannelNode.java
+++ b/src/main/java/IChannelNode.java
@@ -3,13 +3,30 @@ import java.util.Map;
3 3
4public interface IChannelNode extends Comparable<IChannelNode> { 4public interface IChannelNode extends Comparable<IChannelNode> {
5 enum Direction { 5 enum Direction {
6 INCOMING(0), // Users incoming from outside channel (aka: other channel forwarded this channel's post) 6 INCOMING(1), // Users incoming from outside channel (aka: other channel forwarded this channel's post)
7 OUTGOING(1), // Users outgoing from this channel (aka: this channel forwarded someone else's post) 7 OUTGOING(2), // Users outgoing from this channel (aka: this channel forwarded someone else's post)
8 BOTH(2); // Modify both incoming and outgoing counts at once 8 BOTH(3); // Modify both incoming and outgoing counts at once
9 9
10 private final int val; 10 private final int val;
11 Direction(int val) {this.val = val;} 11 Direction(int val) {this.val = val;}
12 public int getVal() {return this.val;} 12 public int getVal() {return this.val;}
13
14 public interface callback {
15 void cb();
16 }
17 public static void overVals(Map<Direction, callback> cmap, Direction dir) throws IllegalArgumentException {
18 if(cmap == null) throw new IllegalArgumentException("callback map is null");
19 if(dir == null) throw new IllegalArgumentException("dir is null");
20 for(Direction cdir: cmap.keySet()) if(cdir == null) throw new IllegalArgumentException("One of the directions is null");
21 for(callback cb: cmap.values()) if(cb == null) throw new IllegalArgumentException("One of the callbacks is null");
22
23 // For each direction in the map, check that the given direction is gte, and if so run the callback
24 for(Direction cdir: cmap.keySet())
25 if(dir.getVal() >= cdir.getVal())
26 cmap.get(cdir).cb();
27 }
28 // This is hilariously overengineered because java fucking sucks my entire cock and balls
29 // Barely even saves any space too
13 } 30 }
14 31
15 void setConnections(Map<IChannelNode, Integer> conmap, Direction dir); 32 void setConnections(Map<IChannelNode, Integer> conmap, Direction dir);
diff --git a/td b/td
new file mode 160000
Subproject 369ee922b45bfa7e8da357e4d62e93925862d86