purpleline.hpp
7.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
#pragma once
#include <string>
#include <deque>
#include <cmds.h>
#include <debug.h>
#include <plugin.h>
#include <prpl.h>
#include "constants.hpp"
#include "thriftclient.hpp"
#include "httpclient.hpp"
#include "poller.hpp"
#include "pinverifier.hpp"
class ThriftClient;
template <typename T>
struct _blist_node_type { };
template <>
struct _blist_node_type<PurpleBuddy> {
static const PurpleBlistNodeType type = PURPLE_BLIST_BUDDY_NODE;
static PurpleAccount *get_account(PurpleBuddy *buddy) {
return purple_buddy_get_account(buddy);
}
};
template <>
struct _blist_node_type<PurpleChat> {
static const PurpleBlistNodeType type = PURPLE_BLIST_CHAT_NODE;
static PurpleAccount *get_account(PurpleChat *chat) {
return purple_chat_get_account(chat);
}
};
enum class ChatType {
ANY = 0,
GROUP = 1,
ROOM = 2,
GROUP_INVITE = 3,
};
std::string markup_escape(std::string const &text);
std::string markup_unescape(std::string const &markup);
std::string url_encode(std::string const &str);
class PurpleLine {
struct Attachment {
line::ContentType::type type;
std::string id;
std::string path;
Attachment(line::ContentType::type type, std::string id)
: type(type), id(id)
{
}
};
static std::map<ChatType, std::string> chat_type_to_string;
PurpleConnection *conn;
PurpleAccount *acct;
boost::shared_ptr<ThriftClient> c_out;
HTTPClient http;
// Remove if libpurple HTTP ever gets support for binary request bodies
LineHttpTransport os_http;
friend class Poller;
Poller poller;
friend class PINVerifier;
PINVerifier pin_verifier;
int next_purple_id;
std::deque<std::string> recent_messages;
std::vector<std::string> temp_files;
line::Profile profile;
line::Contact profile_contact; // contains some fields from profile
line::Contact no_contact; // empty object
std::map<std::string, line::Group> groups;
std::map<std::string, line::Room> rooms;
std::map<std::string, line::Contact> contacts;
void *pin_ui_handle;
guint pin_timeout;
public:
PurpleLine(PurpleConnection *conn, PurpleAccount *acct);
~PurpleLine();
static void register_commands();
static const char *list_icon(PurpleAccount *, PurpleBuddy *buddy);
static GList *status_types(PurpleAccount *);
static char *status_text(PurpleBuddy *buddy);
static void tooltip_text(PurpleBuddy *buddy, PurpleNotifyUserInfo *user_info, gboolean full);
static void login(PurpleAccount *acct);
void close();
int send_im(const char *who, const char *message, PurpleMessageFlags flags);
void remove_buddy(PurpleBuddy *buddy, PurpleGroup *);
PurpleCmdRet cmd_sticker(PurpleConversation *conv,
const gchar *, gchar **args, gchar **error, void *);
PurpleCmdRet cmd_history(PurpleConversation *conv,
const gchar *, gchar **args, gchar **error, void *);
PurpleCmdRet cmd_open(PurpleConversation *conv,
const gchar *, gchar **args, gchar **error, void *);
private:
void connect_signals();
void disconnect_signals();
std::string get_tmp_dir(bool create=false);
std::string conv_attachment_add(PurpleConversation *conv,
line::ContentType::type type, std::string id);
Attachment *conv_attachment_get(PurpleConversation *conv, std::string token);
void write_message(line::Message &msg, bool replay);
void write_message(PurpleConversation *conv, std::string &from, std::string &text,
time_t mtime, int flags);
std::string get_room_display_name(line::Room &room);
void set_chat_participants(PurpleConvChat *chat, line::Room &room);
void set_chat_participants(PurpleConvChat *chat, line::Group &group);
line::Contact &get_up_to_date_contact(line::Contact &c);
int send_message(std::string to, const char *markup);
void send_message(
line::Message &msg,
std::function<void(line::Message &msg)> callback=std::function<void(line::Message &)>());
void upload_media(std::string message_id, std::string type, std::string data);
void push_recent_message(std::string id);
void signal_blist_node_removed(PurpleBlistNode *node);
void signal_conversation_created(PurpleConversation *conv);
void signal_deleting_conversation(PurpleConversation *conv);
void fetch_conversation_history(PurpleConversation *conv, int count, bool requested);
void notify_error(std::string msg);
// sync
private:
// Login process methods, executed in this this order
void login_start();
void get_auth_token();
std::string get_encrypted_credentials(line::RSAKey &key);
void set_auth_token(std::string auth_token);
void get_last_op_revision();
void get_profile();
void get_contacts();
void get_groups();
void get_rooms();
void update_rooms(line::MessageBoxWrapUpList wrap_up_list);
void get_group_invites();
void login_done();
// blist
private:
template <typename T>
std::set<T *> blist_find(std::function<bool(T *)> predicate);
template <typename T>
std::set<T *> blist_find() {
return blist_find<T>([](T *){ return true; });
}
PurpleGroup *blist_ensure_group(std::string group_name, bool temporary=false);
PurpleBuddy *blist_ensure_buddy(std::string uid, bool temporary=false);
void blist_update_buddy(std::string uid, bool temporary=false);
PurpleBuddy *blist_update_buddy(line::Contact &contact, bool temporary=false);
bool blist_is_buddy_in_any_conversation(std::string uid, PurpleConvChat *ignore_chat);
void blist_remove_buddy(std::string uid,
bool temporary_only=false, PurpleConvChat *ignore_chat=nullptr);
std::set<PurpleChat *> blist_find_chats_by_type(ChatType type);
PurpleChat *blist_find_chat(std::string id, ChatType type);
PurpleChat *blist_ensure_chat(std::string id, ChatType type);
void blist_update_chat(std::string id, ChatType type);
PurpleChat *blist_update_chat(line::Group &group);
PurpleChat *blist_update_chat(line::Room &room);
void blist_remove_chat(std::string id, ChatType type);
// chats
public:
static char *get_chat_name(GHashTable *components);
GList *chat_info();
void join_chat(GHashTable *components);
void reject_chat(GHashTable *components);
void chat_leave(int id);
int chat_send(int id, const char *message, PurpleMessageFlags flags);
PurpleChat *find_blist_chat(const char *name);
private:
static ChatType get_chat_type(const char *type_ptr);
void join_chat_success(ChatType type, std::string id);
void handle_group_invite(line::Group &group, line::Contact &invitee, line::Contact &inviter);
};
template <typename T>
std::set<T *> PurpleLine::blist_find(std::function<bool(T *)> predicate) {
std::set<T *> results;
for (PurpleBlistNode *node = purple_blist_get_root();
node;
node = purple_blist_node_next(node, FALSE))
{
if (purple_blist_node_get_type(node) == _blist_node_type<T>::type
&& _blist_node_type<T>::get_account((T *)node) == acct
&& predicate((T *)node))
{
results.insert((T *)node);
}
}
return results;
}