Add basic .tl parsing

master
Lonami Exo 2018-07-23 13:20:28 +02:00
parent 7b75a31624
commit 68a6d4a49f
7 changed files with 1440 additions and 0 deletions

View File

@ -1,6 +1,11 @@
package io.github.lonamiwebs.overgram;
import io.github.lonamiwebs.overgram.parser.TLReader;
import java.io.File;
public class Overgram {
public static void main(final String... args) {
TLReader.readTlObjects(new File("telegram_api.tl"));
}
}

View File

@ -0,0 +1,21 @@
package io.github.lonamiwebs.overgram.parser;
public class TLArg {
public final String name;
public final String type;
private TLArg(final String name, final String type) {
this.name = name;
this.type = type;
}
public static TLArg fromString(String string) {
final String[] tmp = string.split(":");
return new TLArg(tmp[0], tmp[1]);
}
@Override
public String toString() {
return name + ":" + type;
}
}

View File

@ -0,0 +1,73 @@
package io.github.lonamiwebs.overgram.parser;
import java.util.ArrayList;
import java.util.List;
public class TLObject {
public final String fullname;
public final String namespace;
public final String name;
public final int code;
public final List<TLArg> args;
public final String type;
private TLObject(final String fullname, final int code, final List<TLArg> args, final String type) {
this.fullname = fullname;
this.code = code;
this.args = args;
this.type = type;
final String[] nsName = fullname.split("\\.");
if (nsName.length == 1) {
namespace = "";
name = nsName[0];
} else {
namespace = nsName[0];
name = nsName[1];
}
}
public static TLObject fromString(String string) {
String[] tmp;
String name;
String code;
String type;
tmp = string.split("\\s+=\\s+");
string = tmp[0];
type = tmp[1];
tmp = string.split(" ", 2);
name = tmp[0];
string = tmp.length == 1 ? "" : tmp[1];
tmp = name.split("#");
name = tmp[0];
code = tmp.length == 1 ? "0" : tmp[1];
final List<TLArg> args = new ArrayList<>();
if (!string.isEmpty()) {
for (final String part : string.split(" ")) {
args.add(TLArg.fromString(part));
}
}
return new TLObject(name, Integer.parseUnsignedInt(code, 16), args, type);
}
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append(fullname);
builder.append('#');
builder.append(Integer.toString(code, 16));
for (final TLArg arg : args) {
builder.append(' ');
builder.append(arg.toString());
}
builder.append(" = ");
builder.append(type);
return builder.toString();
}
}

View File

@ -0,0 +1,66 @@
package io.github.lonamiwebs.overgram.parser;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class TLReader {
private static final int BUFFER_SIZE = 4096;
public static List<TLObject> readTlObjects(final File file) {
final List<String> lines = readFileWithDelimiter(new File("telegram_api.tl"), ';');
sanitizeTlLines(lines);
final List<TLObject> objects = new ArrayList<>(lines.size());
for (final String line : lines) {
objects.add(TLObject.fromString(line));
}
return objects;
}
private static List<String> readFileWithDelimiter(final File file, final char delimiter) {
final List<String> result = new ArrayList<>();
try (final FileReader reader = new FileReader(file)) {
int read;
final char[] buffer = new char[BUFFER_SIZE];
final StringBuilder builder = new StringBuilder();
while ((read = reader.read(buffer)) > 0) {
for (int i = 0; i < read; ++i) {
if (buffer[i] == delimiter) {
result.add(builder.toString());
builder.setLength(0);
} else {
builder.append(buffer[i]);
}
}
}
} catch (IOException ignored) {
}
return result;
}
private static void sanitizeTlLines(final List<String> lines) {
String line;
int comment;
int newline;
for (int i = lines.size(); i-- != 0; ) {
line = lines.get(i);
while ((comment = line.indexOf("//")) != -1) {
newline = line.indexOf("\n", comment + 2);
if (newline == -1) {
newline = line.length();
}
line = line.substring(0, comment) + line.substring(newline);
}
line = line.trim();
if (line.isEmpty()) {
lines.remove(i);
} else {
lines.set(i, line);
}
}
}
}

View File

@ -0,0 +1,90 @@
//int ? = Int;
//long ? = Long;
//double ? = Double;
//string ? = String;
dummyHttpWait = HttpWait;
//vector {t:Type} # [ t ] = Vector t;
//int128 4*[ int ] = Int128;
//int256 8*[ int ] = Int256;
resPQ#05162463 nonce:int128 server_nonce:int128 pq:bytes server_public_key_fingerprints:Vector<long> = ResPQ;
p_q_inner_data#83c95aec pq:bytes p:bytes q:bytes nonce:int128 server_nonce:int128 new_nonce:int256 = P_Q_inner_data;
p_q_inner_data_temp#3c6a84d4 pq:bytes p:bytes q:bytes nonce:int128 server_nonce:int128 new_nonce:int256 expires_in:int = P_Q_inner_data;
server_DH_params_fail#79cb045d nonce:int128 server_nonce:int128 new_nonce_hash:int128 = Server_DH_Params;
server_DH_params_ok#d0e8075c nonce:int128 server_nonce:int128 encrypted_answer:bytes = Server_DH_Params;
server_DH_inner_data#b5890dba nonce:int128 server_nonce:int128 g:int dh_prime:bytes g_a:bytes server_time:int = Server_DH_inner_data;
client_DH_inner_data#6643b654 nonce:int128 server_nonce:int128 retry_id:long g_b:bytes = Client_DH_Inner_Data;
dh_gen_ok#3bcbf734 nonce:int128 server_nonce:int128 new_nonce_hash1:int128 = Set_client_DH_params_answer;
dh_gen_retry#46dc1fb9 nonce:int128 server_nonce:int128 new_nonce_hash2:int128 = Set_client_DH_params_answer;
dh_gen_fail#a69dae02 nonce:int128 server_nonce:int128 new_nonce_hash3:int128 = Set_client_DH_params_answer;
bind_auth_key_inner#75a3f765 nonce:long temp_auth_key_id:long perm_auth_key_id:long temp_session_id:long expires_at:int = BindAuthKeyInner;
//rpc_result#f35c6d01 req_msg_id:long result:bytes = RpcResult;
rpc_error#2144ca19 error_code:int error_message:string = RpcError;
rpc_answer_unknown#5e2ad36e = RpcDropAnswer;
rpc_answer_dropped_running#cd78e586 = RpcDropAnswer;
rpc_answer_dropped#a43ad8b7 msg_id:long seq_no:int bytes:int = RpcDropAnswer;
future_salt#0949d9dc valid_since:int valid_until:int salt:long = FutureSalt;
future_salts#ae500895 req_msg_id:long now:int salts:vector<future_salt> = FutureSalts;
pong#347773c5 msg_id:long ping_id:long = Pong;
destroy_session_ok#e22045fc session_id:long = DestroySessionRes;
destroy_session_none#62d350c9 session_id:long = DestroySessionRes;
new_session_created#9ec20908 first_msg_id:long unique_id:long server_salt:long = NewSession;
//msg_container#73f1f8dc messages:vector<%Message> = MessageContainer;
//message msg_id:long seqno:int bytes:int body:bytes = Message;
//msg_copy#e06046b2 orig_message:Message = MessageCopy;
//gzip_packed#3072cfa1 packed_data:bytes = Object;
msgs_ack#62d6b459 msg_ids:Vector<long> = MsgsAck;
bad_msg_notification#a7eff811 bad_msg_id:long bad_msg_seqno:int error_code:int = BadMsgNotification;
bad_server_salt#edab447b bad_msg_id:long bad_msg_seqno:int error_code:int new_server_salt:long = BadMsgNotification;
msg_resend_req#7d861a08 msg_ids:Vector<long> = MsgResendReq;
msgs_state_req#da69fb52 msg_ids:Vector<long> = MsgsStateReq;
msgs_state_info#04deb57d req_msg_id:long info:string = MsgsStateInfo;
msgs_all_info#8cc0d131 msg_ids:Vector<long> info:string = MsgsAllInfo;
msg_detailed_info#276d3ec6 msg_id:long answer_msg_id:long bytes:int status:int = MsgDetailedInfo;
msg_new_detailed_info#809db6df answer_msg_id:long bytes:int status:int = MsgDetailedInfo;
rsa_public_key n:string e:bytes = RSAPublicKey;
---functions---
req_pq_multi#be7e8ef1 nonce:int128 = ResPQ;
req_DH_params#d712e4be nonce:int128 server_nonce:int128 p:bytes q:bytes public_key_fingerprint:long encrypted_data:string = Server_DH_Params;
set_client_DH_params#f5045f1f nonce:int128 server_nonce:int128 encrypted_data:bytes = Set_client_DH_params_answer;
rpc_drop_answer#58e4a740 req_msg_id:long = RpcDropAnswer;
get_future_salts#b921bd04 num:int = FutureSalts;
ping#7abe77ec ping_id:long = Pong;
ping_delay_disconnect#f3427b8c ping_id:long disconnect_delay:int = Pong;
destroy_session#e7512126 session_id:long = DestroySessionRes;
http_wait#9299359f max_delay:int wait_after:int max_wait:int = HttpWait;
//test.useGzipPacked = GzipPacked;
//test.useServerDhInnerData = Server_DH_inner_data;
//test.useNewSessionCreated = NewSession;
//test.useMsgsAck = MsgsAck;
//test.useBadMsgNotification = BadMsgNotification;
//test.useOther key:rsa_public_key p_q_data:P_Q_inner_data dh_data:client_DH_inner_data = RpcError;

File diff suppressed because it is too large Load Diff