basic sync wrapper
This commit is contained in:
parent
8d6f8fda05
commit
6e604860e6
8 changed files with 209 additions and 24 deletions
|
@ -5,17 +5,34 @@
|
||||||
#include <3ds.h>
|
#include <3ds.h>
|
||||||
#include <jansson.h>
|
#include <jansson.h>
|
||||||
|
|
||||||
class MatrixClient {
|
namespace Matrix {
|
||||||
|
|
||||||
|
class Store {
|
||||||
|
public:
|
||||||
|
virtual void setSyncToken(std::string token) = 0;
|
||||||
|
virtual std::string getSyncToken() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Client {
|
||||||
private:
|
private:
|
||||||
|
public:
|
||||||
std::string hsUrl;
|
std::string hsUrl;
|
||||||
std::string token;
|
std::string token;
|
||||||
int requestId;
|
int requestId;
|
||||||
|
bool stopSyncing;
|
||||||
|
Store* store;
|
||||||
|
void startSync();
|
||||||
|
void processSync(json_t* sync);
|
||||||
|
json_t* doSync(std::string token);
|
||||||
|
json_t* doRequest(const char* method, std::string path, json_t* body = NULL);
|
||||||
public:
|
public:
|
||||||
MatrixClient(std::string homeserverUrl, std::string matrixToken);
|
Client(std::string homeserverUrl, std::string matrixToken, Store* clientStore = NULL);
|
||||||
|
std::string userId();
|
||||||
std::string sendTextMessage(std::string roomId, std::string text);
|
std::string sendTextMessage(std::string roomId, std::string text);
|
||||||
std::string sendMessage(std::string roomId, json_t* content);
|
std::string sendMessage(std::string roomId, json_t* content);
|
||||||
std::string sendEvent(std::string roomId, std::string eventType, json_t* content);
|
std::string sendEvent(std::string roomId, std::string eventType, json_t* content);
|
||||||
json_t* doRequest(const char* method, std::string path, json_t* body = NULL);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}; // namespace Matrix
|
||||||
|
|
||||||
#endif // _matrixclient_h_
|
#endif // _matrixclient_h_
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
#ifndef _templatelib_h_
|
|
||||||
#define _templatelib_h_
|
|
||||||
|
|
||||||
int myLibFunction();
|
|
||||||
|
|
||||||
#endif // _templatelib_h_
|
|
|
@ -6,22 +6,46 @@
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include "util.h"
|
||||||
|
#include "memorystore.h"
|
||||||
|
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
||||||
#define SOC_ALIGN 0x1000
|
#define SOC_ALIGN 0x1000
|
||||||
#define SOC_BUFFERSIZE 0x100000
|
#define SOC_BUFFERSIZE 0x100000
|
||||||
|
#define SYNC_TIMEOUT 10000
|
||||||
|
|
||||||
|
namespace Matrix {
|
||||||
|
|
||||||
static u32 *SOC_buffer = NULL;
|
static u32 *SOC_buffer = NULL;
|
||||||
|
|
||||||
MatrixClient::MatrixClient(std::string homeserverUrl, std::string matrixToken) {
|
Client::Client(std::string homeserverUrl, std::string matrixToken, Store* clientStore) {
|
||||||
hsUrl = homeserverUrl;
|
hsUrl = homeserverUrl;
|
||||||
token = matrixToken;
|
token = matrixToken;
|
||||||
requestId = 0;
|
requestId = 0;
|
||||||
|
stopSyncing = false;
|
||||||
|
if (!clientStore) {
|
||||||
|
clientStore = new MemoryStore();
|
||||||
|
}
|
||||||
|
store = clientStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string MatrixClient::sendTextMessage(std::string roomId, std::string text) {
|
std::string Client::userId() {
|
||||||
|
json_t* ret = doRequest("GET", "/_matrix/client/r0/account/whoami");
|
||||||
|
if (!ret) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
json_t* userId = json_object_get(ret, "user_id");
|
||||||
|
if (!userId) {
|
||||||
|
json_decref(ret);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
const char* userIdStr = json_string_value(userId);
|
||||||
|
json_decref(ret);
|
||||||
|
return userIdStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Client::sendTextMessage(std::string roomId, std::string text) {
|
||||||
json_t* request = json_object();
|
json_t* request = json_object();
|
||||||
json_object_set_new(request, "msgtype", json_string("m.text"));
|
json_object_set_new(request, "msgtype", json_string("m.text"));
|
||||||
json_object_set_new(request, "body", json_string(text.c_str()));
|
json_object_set_new(request, "body", json_string(text.c_str()));
|
||||||
|
@ -30,13 +54,13 @@ std::string MatrixClient::sendTextMessage(std::string roomId, std::string text)
|
||||||
return eventId;
|
return eventId;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string MatrixClient::sendMessage(std::string roomId, json_t* content) {
|
std::string Client::sendMessage(std::string roomId, json_t* content) {
|
||||||
return sendEvent(roomId, "m.room.message", content);
|
return sendEvent(roomId, "m.room.message", content);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string MatrixClient::sendEvent(std::string roomId, std::string eventType, json_t* content) {
|
std::string Client::sendEvent(std::string roomId, std::string eventType, json_t* content) {
|
||||||
std::string txid = std::to_string(time(NULL)) + "_REQ_" + std::to_string(requestId);
|
std::string txid = std::to_string(time(NULL)) + "_REQ_" + std::to_string(requestId);
|
||||||
std::string path = "/_matrix/client/r0/rooms/" + roomId + "/send/" + eventType + "/" + txid;
|
std::string path = "/_matrix/client/r0/rooms/" + urlencode(roomId) + "/send/" + urlencode(eventType) + "/" + urlencode(txid);
|
||||||
json_t* ret = doRequest("PUT", path, content);
|
json_t* ret = doRequest("PUT", path, content);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
return "";
|
return "";
|
||||||
|
@ -52,12 +76,95 @@ std::string MatrixClient::sendEvent(std::string roomId, std::string eventType, j
|
||||||
return eventIdStr;
|
return eventIdStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Client::processSync(json_t* sync) {
|
||||||
|
json_t* rooms = json_object_get(sync, "rooms");
|
||||||
|
if (!rooms) {
|
||||||
|
return; // nothing to do
|
||||||
|
}
|
||||||
|
json_t* leftRooms = json_object_get(rooms, "leave");
|
||||||
|
json_t* invitedRooms = json_object_get(rooms, "invite");
|
||||||
|
json_t* joinedRooms = json_object_get(rooms, "join");
|
||||||
|
|
||||||
|
const char* roomId;
|
||||||
|
json_t* room;
|
||||||
|
|
||||||
|
if (leftRooms) {
|
||||||
|
json_object_foreach(leftRooms, roomId, room) {
|
||||||
|
// rooms that we left
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (invitedRooms) {
|
||||||
|
json_object_foreach(invitedRooms, roomId, room) {
|
||||||
|
// rooms that we were invited to
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (joinedRooms) {
|
||||||
|
json_object_foreach(joinedRooms, roomId, room) {
|
||||||
|
// rooms that we are joined
|
||||||
|
printf(roomId);
|
||||||
|
printf(":\n");
|
||||||
|
json_t* timeline = json_object_get(room, "timeline");
|
||||||
|
if (!timeline) {
|
||||||
|
printf("no timeline\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
json_t* events = json_object_get(timeline, "events");
|
||||||
|
if (!events) {
|
||||||
|
printf("no events\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
size_t index;
|
||||||
|
json_t* event;
|
||||||
|
json_array_foreach(events, index, event) {
|
||||||
|
json_t* eventType = json_object_get(event, "type");
|
||||||
|
printf(json_string_value(eventType));
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::startSync() {
|
||||||
|
std::string token = store->getSyncToken();
|
||||||
|
if (stopSyncing) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
json_t* ret = doSync(token);
|
||||||
|
if (ret) {
|
||||||
|
// set the token for the next batch
|
||||||
|
json_t* token = json_object_get(ret, "next_batch");
|
||||||
|
if (token) {
|
||||||
|
printf("Found next batch\n");
|
||||||
|
store->setSyncToken(json_string_value(token));
|
||||||
|
} else {
|
||||||
|
printf("No next batch\n");
|
||||||
|
store->setSyncToken("");
|
||||||
|
}
|
||||||
|
processSync(ret);
|
||||||
|
json_decref(ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
json_t* Client::doSync(std::string token) {
|
||||||
|
printf("Doing sync with token ");
|
||||||
|
printf(token.c_str());
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
std::string query = "?full_state=false&timeout=" + std::to_string(SYNC_TIMEOUT);
|
||||||
|
if (token != "") {
|
||||||
|
query += "&since=" + token;
|
||||||
|
}
|
||||||
|
return doRequest("GET", "/_matrix/client/r0/sync" + query);
|
||||||
|
}
|
||||||
|
|
||||||
size_t DoRequestWriteCallback(char *contents, size_t size, size_t nmemb, void *userp) {
|
size_t DoRequestWriteCallback(char *contents, size_t size, size_t nmemb, void *userp) {
|
||||||
((std::string*)userp)->append((char*)contents, size * nmemb);
|
((std::string*)userp)->append((char*)contents, size * nmemb);
|
||||||
return size * nmemb;
|
return size * nmemb;
|
||||||
}
|
}
|
||||||
|
|
||||||
json_t* MatrixClient::doRequest(const char* method, std::string path, json_t* body) {
|
json_t* Client::doRequest(const char* method, std::string path, json_t* body) {
|
||||||
std::string url = hsUrl + path;
|
std::string url = hsUrl + path;
|
||||||
requestId++;
|
requestId++;
|
||||||
|
|
||||||
|
@ -101,6 +208,7 @@ json_t* MatrixClient::doRequest(const char* method, std::string path, json_t* bo
|
||||||
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, method);
|
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, method);
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, DoRequestWriteCallback);
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, DoRequestWriteCallback);
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L);
|
||||||
|
|
||||||
// curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
|
// curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
|
||||||
// curl_easy_setopt(curl, CURLOPT_STDERR, stdout);
|
// curl_easy_setopt(curl, CURLOPT_STDERR, stdout);
|
||||||
|
@ -111,8 +219,8 @@ json_t* MatrixClient::doRequest(const char* method, std::string path, json_t* bo
|
||||||
}
|
}
|
||||||
curl_easy_cleanup(curl);
|
curl_easy_cleanup(curl);
|
||||||
|
|
||||||
printf(readBuffer.c_str());
|
// printf(readBuffer.c_str());
|
||||||
printf("\n");
|
// printf("\n");
|
||||||
json_error_t error;
|
json_error_t error;
|
||||||
json_t* content = json_loads(readBuffer.c_str(), 0, &error);
|
json_t* content = json_loads(readBuffer.c_str(), 0, &error);
|
||||||
if (!content) {
|
if (!content) {
|
||||||
|
@ -121,3 +229,5 @@ json_t* MatrixClient::doRequest(const char* method, std::string path, json_t* bo
|
||||||
}
|
}
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}; // namespace Matrix
|
||||||
|
|
18
source/memorystore.cpp
Normal file
18
source/memorystore.cpp
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#include "memorystore.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace Matrix {
|
||||||
|
|
||||||
|
MemoryStore::MemoryStore() {
|
||||||
|
syncToken = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryStore::setSyncToken(std::string token) {
|
||||||
|
syncToken = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string MemoryStore::getSyncToken() {
|
||||||
|
return syncToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // namespace Matrix
|
20
source/memorystore.h
Normal file
20
source/memorystore.h
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef _memorystore_h_
|
||||||
|
#define _memorystore_h_
|
||||||
|
|
||||||
|
#include "../include/matrixclient.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace Matrix {
|
||||||
|
|
||||||
|
class MemoryStore : public Store {
|
||||||
|
private:
|
||||||
|
std::string syncToken;
|
||||||
|
public:
|
||||||
|
MemoryStore();
|
||||||
|
void setSyncToken(std::string token);
|
||||||
|
std::string getSyncToken();
|
||||||
|
};
|
||||||
|
|
||||||
|
}; // namespace Matrix
|
||||||
|
|
||||||
|
#endif // _memorystore_h_
|
|
@ -1,6 +0,0 @@
|
||||||
int myLibFunction() {
|
|
||||||
|
|
||||||
|
|
||||||
return 42;
|
|
||||||
|
|
||||||
}
|
|
24
source/util.cpp
Normal file
24
source/util.cpp
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#include "util.h"
|
||||||
|
#include <string>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
// from http://www.zedwood.com/article/cpp-urlencode-function
|
||||||
|
std::string urlencode(std::string s) {
|
||||||
|
static const char lookup[]= "0123456789abcdef";
|
||||||
|
std::stringstream e;
|
||||||
|
for(int i = 0, ix = s.length(); i < ix; i++) {
|
||||||
|
const char& c = s[i];
|
||||||
|
if ( (48 <= c && c <= 57) ||//0-9
|
||||||
|
(65 <= c && c <= 90) ||//abc...xyz
|
||||||
|
(97 <= c && c <= 122) || //ABC...XYZ
|
||||||
|
(c=='-' || c=='_' || c=='.' || c=='~')
|
||||||
|
) {
|
||||||
|
e << c;
|
||||||
|
} else {
|
||||||
|
e << '%';
|
||||||
|
e << lookup[ (c&0xF0)>>4 ];
|
||||||
|
e << lookup[ (c&0x0F) ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return e.str();
|
||||||
|
}
|
8
source/util.h
Normal file
8
source/util.h
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef _UTIL_H_
|
||||||
|
#define _UTIL_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
std::string urlencode(std::string str);
|
||||||
|
|
||||||
|
#endif // _UTIL_H_
|
Loading…
Reference in a new issue