Add possibillity to listen to created users, chats and groups with event handlers and add some ability to exchange output functions with own callbacks
This commit is contained in:
parent
dbf509d59e
commit
d712b7e17f
7 changed files with 202 additions and 11 deletions
27
loop.c
27
loop.c
|
@ -536,6 +536,10 @@ void network_connect (void) {
|
|||
write_auth_file ();
|
||||
logprintf("DataCentre start_loopd, key id: %lld\n", DC_list[i]->auth_key_id);
|
||||
}
|
||||
|
||||
// read saved connection state
|
||||
read_state_file ();
|
||||
read_secret_chat_file ();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -625,6 +629,25 @@ void network_export_registration()
|
|||
fflush (stderr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch all unknown messages of the current session
|
||||
*/
|
||||
void session_get_difference()
|
||||
{
|
||||
do_get_difference();
|
||||
net_loop (0, dgot);
|
||||
}
|
||||
|
||||
extern int contacts_got;
|
||||
int cupdate_got() {
|
||||
return contacts_got;
|
||||
}
|
||||
void session_update_contact_list()
|
||||
{
|
||||
do_update_contact_list();
|
||||
net_loop(0, cupdate_got);
|
||||
}
|
||||
|
||||
int start_loop (char* code, char* auth_mode) {
|
||||
logprintf("Calling start_loop()\n");
|
||||
logprintf("auth_state %i\n", auth_state);
|
||||
|
@ -722,9 +745,11 @@ int start_loop (char* code, char* auth_mode) {
|
|||
fflush (stdout);
|
||||
fflush (stderr);
|
||||
|
||||
// read saved connection state
|
||||
read_state_file ();
|
||||
read_secret_chat_file ();
|
||||
|
||||
|
||||
// callbacks for interface functions
|
||||
set_interface_callbacks ();
|
||||
|
||||
do_get_difference ();
|
||||
|
|
|
@ -66,6 +66,8 @@
|
|||
|
||||
#include "mtproto-common.h"
|
||||
|
||||
#include "tg-cli.h"
|
||||
|
||||
#define MAX_NET_RES (1L << 16)
|
||||
extern int log_level;
|
||||
|
||||
|
@ -906,6 +908,7 @@ void work_update_binlog (void) {
|
|||
|
||||
void work_update (struct connection *c UU, long long msg_id UU) {
|
||||
unsigned op = fetch_int ();
|
||||
logprintf("work_update(): OP:%d\n", op);
|
||||
switch (op) {
|
||||
case CODE_update_new_message:
|
||||
{
|
||||
|
@ -913,7 +916,8 @@ void work_update (struct connection *c UU, long long msg_id UU) {
|
|||
assert (M);
|
||||
fetch_pts ();
|
||||
unread_messages ++;
|
||||
print_message (M);
|
||||
event_update_new_message(M);
|
||||
//print_message (M);
|
||||
update_prompt ();
|
||||
break;
|
||||
};
|
||||
|
@ -1717,10 +1721,12 @@ int rpc_execute (struct connection *c, int op, int len) {
|
|||
if (verbosity) {
|
||||
logprintf ( "outbound rpc connection #%d : received rpc answer %d with %d content bytes\n", c->fd, op, len);
|
||||
}
|
||||
/* if (op < 0) {
|
||||
/*
|
||||
if (op < 0) {
|
||||
assert (read_in (c, Response, Response_len) == Response_len);
|
||||
return 0;
|
||||
}*/
|
||||
}
|
||||
*/
|
||||
|
||||
if (len >= MAX_RESPONSE_SIZE/* - 12*/ || len < 0/*12*/) {
|
||||
logprintf ( "answer too long (%d bytes), skipping\n", len);
|
||||
|
|
54
net.c
54
net.c
|
@ -59,6 +59,43 @@ extern FILE *log_net_f;
|
|||
|
||||
void fail_connection (struct connection *c);
|
||||
|
||||
/*
|
||||
* Delegate the read-oprations to external function
|
||||
*/
|
||||
ssize_t (*netread)(int fd, void *buff, size_t size) = read;
|
||||
void set_net_read_cb(ssize_t (*cb)(int fd, void *buff, size_t size)) {
|
||||
netread = cb;
|
||||
}
|
||||
|
||||
/*
|
||||
* Delegate the write operations to external function
|
||||
*/
|
||||
ssize_t (*netwrite)(int fd, const void *buff, size_t size) = write;
|
||||
void set_net_write_cb(ssize_t (*cb)(int fd, const void *buff, size_t size)) {
|
||||
netwrite = cb;
|
||||
}
|
||||
|
||||
/*
|
||||
* Delegate the session creation to an external callback
|
||||
*
|
||||
* TODO: use dc_ensure_session instead of dc_create_session to create sessions,
|
||||
* to make this actually work
|
||||
*/
|
||||
void dc_create_session (struct dc *DC);
|
||||
void dc_ensure_session_local (struct dc *DC, void (*on_session_ready)(void)) {
|
||||
dc_create_session(DC);
|
||||
on_session_ready();
|
||||
}
|
||||
void (*dc_ensure_session)(struct dc *DC, void (*on_session_ready)(void));
|
||||
void set_dc_ensure_session_cb (void (*dc_ens_sess)(struct dc *DC, void (*on_session_ready)(void)))
|
||||
{
|
||||
dc_ensure_session = dc_ens_sess;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
||||
#define PING_TIMEOUT 10
|
||||
|
||||
void start_ping_timer (struct connection *c);
|
||||
|
@ -386,22 +423,29 @@ void try_write (struct connection *c) {
|
|||
}
|
||||
int x = 0;
|
||||
while (c->out_head) {
|
||||
int r = write (c->fd, c->out_head->rptr, c->out_head->wptr - c->out_head->rptr);
|
||||
int r = netwrite (c->fd, c->out_head->rptr, c->out_head->wptr - c->out_head->rptr);
|
||||
|
||||
// Log all written packages
|
||||
if (r > 0 && log_net_f) {
|
||||
fprintf (log_net_f, "%.02lf %d OUT %s:%d", get_utime (CLOCK_REALTIME), r, c->ip, c->port);
|
||||
int i;
|
||||
for (i = 0; i < r; i++) {
|
||||
|
||||
fprintf (log_net_f, " %02x", *(unsigned char *)(c->out_head->rptr + i));
|
||||
}
|
||||
fprintf (log_net_f, "\n");
|
||||
fflush (log_net_f);
|
||||
}
|
||||
|
||||
if (r >= 0) {
|
||||
x += r;
|
||||
c->out_head->rptr += r;
|
||||
if (c->out_head->rptr != c->out_head->wptr) {
|
||||
// Inhalt des Buffers nicht komplett abgeschickt,
|
||||
// es geht nichts mehr in den Socket
|
||||
break;
|
||||
}
|
||||
// buffer ausgelesen, alten buffer löschen
|
||||
struct connection_buffer *b = c->out_head;
|
||||
c->out_head = b->next;
|
||||
if (!c->out_head) {
|
||||
|
@ -497,11 +541,12 @@ void try_read (struct connection *c) {
|
|||
}
|
||||
int x = 0;
|
||||
while (1) {
|
||||
int r = read (c->fd, c->in_tail->wptr, c->in_tail->end - c->in_tail->wptr);
|
||||
int r = netread (c->fd, c->in_tail->wptr, c->in_tail->end - c->in_tail->wptr);
|
||||
if (r > 0 && log_net_f) {
|
||||
fprintf (log_net_f, "%.02lf %d IN %s:%d", get_utime (CLOCK_REALTIME), r, c->ip, c->port);
|
||||
int i;
|
||||
for (i = 0; i < r; i++) {
|
||||
// print all writte bits
|
||||
fprintf (log_net_f, " %02x", *(unsigned char *)(c->in_tail->wptr + i));
|
||||
}
|
||||
fprintf (log_net_f, "\n");
|
||||
|
@ -509,13 +554,17 @@ void try_read (struct connection *c) {
|
|||
}
|
||||
if (r > 0) {
|
||||
c->last_receive_time = get_double_time ();
|
||||
// reset ping timer
|
||||
stop_ping_timer (c);
|
||||
start_ping_timer (c);
|
||||
}
|
||||
if (r >= 0) {
|
||||
// write pointer nach vorne setzen
|
||||
c->in_tail->wptr += r;
|
||||
x += r;
|
||||
|
||||
if (c->in_tail->wptr != c->in_tail->end) {
|
||||
// Paket nicht komplett beschrieben, keine neuen Daten liegen an.
|
||||
break;
|
||||
}
|
||||
struct connection_buffer *b = new_connection_buffer (1 << 20);
|
||||
|
@ -646,3 +695,4 @@ void dc_create_session (struct dc *DC) {
|
|||
assert (!DC->sessions[0]);
|
||||
DC->sessions[0] = S;
|
||||
}
|
||||
|
||||
|
|
17
queries.c
17
queries.c
|
@ -53,6 +53,7 @@
|
|||
|
||||
#include "no-preview.h"
|
||||
#include "binlog.h"
|
||||
#include "tg-cli.h"
|
||||
|
||||
#define sha1 SHA1
|
||||
|
||||
|
@ -132,7 +133,6 @@ struct query *send_query (struct dc *DC, int ints, void *data, struct query_meth
|
|||
if (!DC->sessions[0]) {
|
||||
dc_create_session (DC);
|
||||
}
|
||||
logprintf("telegram: verbosity: %d\n", verbosity);
|
||||
if (verbosity) {
|
||||
logprintf ( "Sending query of size %d to DC (%s:%d)\n", 4 * ints, DC->ip, DC->port);
|
||||
}
|
||||
|
@ -695,6 +695,7 @@ int do_send_code_result_auth (const char *code, const char *sms_hash, const char
|
|||
/* {{{ Get contacts */
|
||||
extern char *user_list[];
|
||||
|
||||
int contacts_got = 0;
|
||||
int get_contacts_on_answer (struct query *q UU) {
|
||||
int i;
|
||||
assert (fetch_int () == (int)CODE_contacts_contacts);
|
||||
|
@ -708,7 +709,8 @@ int get_contacts_on_answer (struct query *q UU) {
|
|||
assert (fetch_int () == CODE_vector);
|
||||
n = fetch_int ();
|
||||
for (i = 0; i < n; i++) {
|
||||
struct user *U = fetch_alloc_user ();
|
||||
fetch_alloc_user ();
|
||||
/*
|
||||
print_start ();
|
||||
push_color (COLOR_YELLOW);
|
||||
logprintf ("User #%d: ", get_peer_id (U->id));
|
||||
|
@ -735,7 +737,9 @@ int get_contacts_on_answer (struct query *q UU) {
|
|||
}
|
||||
pop_color ();
|
||||
print_end ();
|
||||
*/
|
||||
}
|
||||
contacts_got = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -745,11 +749,14 @@ struct query_methods get_contacts_methods = {
|
|||
|
||||
|
||||
void do_update_contact_list (void) {
|
||||
contacts_got = 0;
|
||||
clear_packet ();
|
||||
out_int (CODE_contacts_get_contacts);
|
||||
out_string ("");
|
||||
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_contacts_methods, 0);
|
||||
}
|
||||
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Encrypt decrypted */
|
||||
|
@ -2565,6 +2572,7 @@ int unread_messages;
|
|||
int difference_got;
|
||||
int seq, pts, qts, last_date;
|
||||
int get_state_on_answer (struct query *q UU) {
|
||||
logprintf("get_state_on_answer()\n");
|
||||
assert (fetch_int () == (int)CODE_updates_state);
|
||||
bl_do_set_pts (fetch_int ());
|
||||
bl_do_set_qts (fetch_int ());
|
||||
|
@ -2578,6 +2586,7 @@ int get_state_on_answer (struct query *q UU) {
|
|||
|
||||
int get_difference_active;
|
||||
int get_difference_on_answer (struct query *q UU) {
|
||||
logprintf("get_difference_on_answer()\n");
|
||||
get_difference_active = 0;
|
||||
unsigned x = fetch_int ();
|
||||
if (x == CODE_updates_difference_empty) {
|
||||
|
@ -2629,7 +2638,8 @@ int get_difference_on_answer (struct query *q UU) {
|
|||
unread_messages = fetch_int ();
|
||||
write_state_file ();
|
||||
for (i = 0; i < ml_pos; i++) {
|
||||
print_message (ML[i]);
|
||||
event_update_new_message(ML[i]);
|
||||
//print_message (ML[i]);
|
||||
}
|
||||
if (x == CODE_updates_difference_slice) {
|
||||
do_get_difference ();
|
||||
|
@ -2651,6 +2661,7 @@ struct query_methods get_difference_methods = {
|
|||
};
|
||||
|
||||
void do_get_difference (void) {
|
||||
logprintf("do_get_difference()\n");
|
||||
get_difference_active = 1;
|
||||
difference_got = 0;
|
||||
clear_packet ();
|
||||
|
|
27
structures.c
27
structures.c
|
@ -33,6 +33,8 @@
|
|||
#include "queries.h"
|
||||
#include "binlog.h"
|
||||
|
||||
#include "tg-cli.h"
|
||||
|
||||
#define sha1 SHA1
|
||||
|
||||
static int id_cmp (struct message *M1, struct message *M2);
|
||||
|
@ -204,6 +206,21 @@ long long fetch_user_photo (struct user *U) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int user_get_printname(peer_t *user, char *buffer, int maxlen)
|
||||
{
|
||||
char* last_name = (user->user.last_name && strlen(user->user.last_name)) ? user->user.last_name : "";
|
||||
char* first_name = (user->user.first_name && strlen(user->user.first_name)) ? user->user.first_name : "";
|
||||
if (strlen(first_name) && strlen(last_name)) {
|
||||
return snprintf(buffer, maxlen, "%s %s", first_name, last_name);
|
||||
} else if (strlen(first_name)) {
|
||||
return snprintf(buffer, maxlen, "%s", first_name);
|
||||
} else if (strlen(last_name)) {
|
||||
return snprintf(buffer, maxlen, "%s", last_name);
|
||||
} else {
|
||||
return snprintf(buffer, maxlen, "%d", get_peer_id(user->id));
|
||||
}
|
||||
}
|
||||
|
||||
int fetch_user (struct user *U) {
|
||||
unsigned x = fetch_int ();
|
||||
code_assert (x == CODE_user_empty || x == CODE_user_self || x == CODE_user_contact || x == CODE_user_request || x == CODE_user_foreign || x == CODE_user_deleted);
|
||||
|
@ -1512,10 +1529,12 @@ static int id_cmp (struct message *M1, struct message *M2) {
|
|||
}
|
||||
|
||||
struct user *fetch_alloc_user (void) {
|
||||
int send_event = 0;
|
||||
int data[2];
|
||||
prefetch_data (data, 8);
|
||||
peer_t *U = user_chat_get (MK_USER (data[1]));
|
||||
if (!U) {
|
||||
send_event = 1;
|
||||
users_allocated ++;
|
||||
U = talloc0 (sizeof (*U));
|
||||
U->id = MK_USER (data[1]);
|
||||
|
@ -1524,6 +1543,9 @@ struct user *fetch_alloc_user (void) {
|
|||
Peers[peer_num ++] = U;
|
||||
}
|
||||
fetch_user (&U->user);
|
||||
if (send_event) {
|
||||
event_user_allocated(U);
|
||||
}
|
||||
return &U->user;
|
||||
}
|
||||
|
||||
|
@ -1871,10 +1893,12 @@ struct message *fetch_alloc_message_short_chat (void) {
|
|||
}
|
||||
|
||||
struct chat *fetch_alloc_chat (void) {
|
||||
int send_event = 0;
|
||||
int data[2];
|
||||
prefetch_data (data, 8);
|
||||
peer_t *U = user_chat_get (MK_CHAT (data[1]));
|
||||
if (!U) {
|
||||
send_event = 1;
|
||||
chats_allocated ++;
|
||||
U = talloc0 (sizeof (*U));
|
||||
U->id = MK_CHAT (data[1]);
|
||||
|
@ -1883,6 +1907,9 @@ struct chat *fetch_alloc_chat (void) {
|
|||
Peers[peer_num ++] = U;
|
||||
}
|
||||
fetch_chat (&U->chat);
|
||||
if (send_event) {
|
||||
event_chat_allocated(U);
|
||||
}
|
||||
return &U->chat;
|
||||
}
|
||||
|
||||
|
|
|
@ -156,6 +156,7 @@ struct user {
|
|||
char *real_last_name;
|
||||
};
|
||||
|
||||
|
||||
struct chat_user {
|
||||
int user_id;
|
||||
int inviter_id;
|
||||
|
@ -380,6 +381,8 @@ void peer_insert_name (peer_t *P);
|
|||
void peer_delete_name (peer_t *P);
|
||||
peer_t *peer_lookup_name (const char *s);
|
||||
|
||||
int user_get_printname(peer_t *user, char *buffer, int maxlen);
|
||||
|
||||
#define PEER_USER 1
|
||||
#define PEER_CHAT 2
|
||||
#define PEER_GEO_CHAT 3
|
||||
|
|
73
tg-cli.h
73
tg-cli.h
|
@ -1,12 +1,15 @@
|
|||
#include <sys/types.h>
|
||||
#include "net.h"
|
||||
#include "mtproto-common.h"
|
||||
#include "structures.h"
|
||||
|
||||
// Export functions for plugins
|
||||
|
||||
int tg_login ();
|
||||
|
||||
void running_for_first_time ();
|
||||
|
||||
void parse_config ();
|
||||
void store_config ();
|
||||
|
||||
void read_auth_file ();
|
||||
|
||||
/**
|
||||
|
@ -40,6 +43,72 @@ int network_phone_is_registered();
|
|||
*/
|
||||
int network_client_is_registered();
|
||||
|
||||
/**
|
||||
* Export the current registration to all available data centers
|
||||
*/
|
||||
void network_export_registration();
|
||||
|
||||
/**
|
||||
* Fetch all unknown messages of the current session
|
||||
*/
|
||||
void session_get_difference();
|
||||
|
||||
/**
|
||||
* Fetch all known contacts
|
||||
*/
|
||||
void session_update_contact_list();
|
||||
|
||||
/*
|
||||
* Events
|
||||
*/
|
||||
void on_update_new_message(void (*on_msg)(struct message *M));
|
||||
void event_update_new_message(struct message *M);
|
||||
|
||||
void on_update_user_typing();
|
||||
void on_update_chat_user_typing();
|
||||
void on_update_user_status();
|
||||
void on_update_user_name();
|
||||
void on_update_user_photo();
|
||||
void on_update_chat_participants();
|
||||
|
||||
/*
|
||||
* Load known users and chats on connect
|
||||
*/
|
||||
void on_user_allocated();
|
||||
|
||||
void on_user_allocated(void (*handler)(peer_t *user));
|
||||
void event_user_allocated(peer_t *user);
|
||||
|
||||
void on_chat_allocated(void (*handler)(peer_t *chat));
|
||||
void event_chat_allocated(peer_t *chat);
|
||||
|
||||
// template
|
||||
//void on_blarg(void (*on_msg)(struct message *M));
|
||||
//void event_blarg(struct message *M);
|
||||
|
||||
void on_chat_allocated();
|
||||
|
||||
/**
|
||||
* Set a function to use as a handle to read from a network resource
|
||||
* instead of the regular socket read function
|
||||
*/
|
||||
void set_net_read_cb(int (*cb)(int fd, void *buff, size_t size));
|
||||
|
||||
/**
|
||||
* Set a function to use as handle to write to a newtork resource
|
||||
* instead of the regular socket write function
|
||||
*/
|
||||
void set_net_write_cb(int (*cb)(int fd, const void *buff, size_t size));
|
||||
|
||||
/**
|
||||
* Set a function to use as handle to create new connections instead of the regular
|
||||
* socket write function
|
||||
*/
|
||||
void set_dc_ensure_session_cb (void (*dc_ens_sess)(struct dc *DC, void (*on_session_ready)(void)));
|
||||
|
||||
/**
|
||||
* ?
|
||||
*/
|
||||
void set_default_username ();
|
||||
// Settings
|
||||
#define AUTH_MODE_SMS "sms"
|
||||
|
|
Loading…
Add table
Reference in a new issue