grim/purple-spasm

255ea8d6611e
Parents c474a88e8ea4
Children c81e3dbaad99
Initial basic support for using the rest api
  • +12 -5
    Makefile
  • +99 -0
    spasm-account.c
  • +20 -5
    spasm-account.h
  • +23 -15
    spasm-auth.c
  • +3 -1
    spasm-const.h
  • +123 -0
    spasm-rest.c
  • +37 -0
    spasm-rest.h
  • +66 -0
    spasm-user.c
  • +33 -0
    spasm-user.h
  • --- a/Makefile Thu May 04 23:13:55 2017 -0500
    +++ b/Makefile Tue May 09 22:50:39 2017 -0500
    @@ -6,14 +6,21 @@
    PLUGIN_NAME := purple-spasm
    PLUGIN_VERSION := 0.0.1
    PLUGIN_CFLAGS := \
    - $(shell pkg-config --cflags json-glib-1.0)
    -PLUGIN_LIBRARIES := \
    - $(shell pkg-config --libs json-glib-1.0)
    + $(shell pkg-config --cflags json-glib-1.0) \
    + $(shell pkg-config --cflags libsoup-2.4)
    +PLUGIN_LIBS := \
    + $(shell pkg-config --libs json-glib-1.0) \
    + $(shell pkg-config --libs libsoup-2.4)
    PLUGIN_SOURCES := \
    spasm.c \
    - spasm-auth.c
    + spasm-account.c \
    + spasm-auth.c \
    + spasm-rest.c \
    + spasm-user.c
    PLUGIN_HEADERS := \
    spasm-account.h \
    spasm-auth.h \
    - spasm-const.h
    + spasm-const.h \
    + spasm-rest.h \
    + spasm-user.h
    include libpurple.mk
    --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/spasm-account.c Tue May 09 22:50:39 2017 -0500
    @@ -0,0 +1,99 @@
    +/*
    + * PurpleSpasm - A Twitch Protocol Plugin
    + * Copyright (C) 2017 Gary Kramlich <grim@reaperworld.com>
    + *
    + * This program is free software; you can redistribute it and/or
    + * modify it under the terms of the GNU General Public License
    + * as published by the Free Software Foundation; either version 2
    + * of the License, or (at your option) any later version.
    + *
    + * This program is distributed in the hope that it will be useful,
    + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    + * GNU General Public License for more details.
    + *
    + * You should have received a copy of the GNU General Public License
    + * along with this program; if not, write to the Free Software
    + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
    + */
    +
    +#include "spasm-account.h"
    +
    +struct _PurpleSpasmAccount {
    + PurpleAccount *account;
    + PurpleConnection *connection;
    +
    + SoupSession *session;
    + gchar *access_token;
    +};
    +
    +/******************************************************************************
    + * API
    + *****************************************************************************/
    +PurpleSpasmAccount *
    +purple_spasm_account_new(PurpleAccount *account, PurpleConnection *connection) {
    + PurpleSpasmAccount *sa = NULL;
    +
    + sa = g_new0(PurpleSpasmAccount, 1);
    +
    + sa->account = account;
    + sa->connection = connection;
    +
    + sa->session = soup_session_new();
    +
    + SoupLogger *logger = soup_logger_new(SOUP_LOGGER_LOG_BODY, -1);
    + soup_session_add_feature(sa->session, SOUP_SESSION_FEATURE(logger));
    +
    +
    + return sa;
    +}
    +
    +void
    +purple_spasm_account_free(PurpleSpasmAccount *sa) {
    + g_return_if_fail(sa);
    +
    + g_object_unref(G_OBJECT(sa->session));
    +
    + g_free(sa);
    +}
    +
    +PurpleAccount *
    +purple_spasm_account_get_account(const PurpleSpasmAccount *sa) {
    + g_return_val_if_fail(sa, NULL);
    +
    + return sa->account;
    +}
    +
    +PurpleConnection *
    +purple_spasm_account_get_connection(const PurpleSpasmAccount *sa) {
    + g_return_val_if_fail(sa, NULL);
    +
    + return sa->connection;
    +}
    +
    +SoupSession *
    +purple_spasm_account_get_session(const PurpleSpasmAccount *sa) {
    + g_return_val_if_fail(sa, NULL);
    +
    + if(sa->session) {
    + return g_object_ref(G_OBJECT(sa->session));
    + }
    +
    + return NULL;
    +}
    +
    +void
    +purple_spasm_account_set_access_token(PurpleSpasmAccount *sa,
    + const gchar *access_token)
    +{
    + g_return_if_fail(sa);
    +
    + sa->access_token = (access_token) ? g_strdup(access_token) : NULL;
    +}
    +
    +const gchar *
    +purple_spasm_account_get_access_token(const PurpleSpasmAccount *sa) {
    + g_return_val_if_fail(sa, NULL);
    +
    + return sa->access_token;
    +}
    --- a/spasm-account.h Thu May 04 23:13:55 2017 -0500
    +++ b/spasm-account.h Tue May 09 22:50:39 2017 -0500
    @@ -22,13 +22,28 @@
    #include <glib.h>
    +#include <libsoup/soup.h>
    +
    #include "account.h"
    #include "connection.h"
    -typedef struct {
    - PurpleAccount *account;
    - PurpleConnection *connection;
    - gchar *access_token;
    -} SpasmAccount;
    +#define PURPLE_SPASM_ACCOUNT(obj) ((PurpleSpasmAccount *)(obj))
    +
    +typedef struct _PurpleSpasmAccount PurpleSpasmAccount;
    +
    +G_BEGIN_DECLS
    +
    +PurpleSpasmAccount *purple_spasm_account_new(PurpleAccount *account, PurpleConnection *connection);
    +void purple_spasm_account_free(PurpleSpasmAccount *sa);
    +
    +PurpleAccount *purple_spasm_account_get_account(const PurpleSpasmAccount *sa);
    +PurpleConnection *purple_spasm_account_get_connection(const PurpleSpasmAccount *sa);
    +
    +SoupSession *purple_spasm_account_get_session(const PurpleSpasmAccount *sa);
    +
    +void purple_spasm_account_set_access_token(PurpleSpasmAccount *sa, const gchar *access_token);
    +const gchar * purple_spasm_account_get_access_token(const PurpleSpasmAccount *sa);
    +
    +G_END_DECLS
    #endif /* PURPLE_SPASM_ACCOUNT_H */
    --- a/spasm-auth.c Thu May 04 23:13:55 2017 -0500
    +++ b/spasm-auth.c Tue May 09 22:50:39 2017 -0500
    @@ -17,35 +17,46 @@
    * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
    */
    +#include <libsoup/soup.h>
    +
    #include "request.h"
    #include "spasm-account.h"
    #include "spasm-auth.h"
    #include "spasm-const.h"
    +#include "spasm-user.h"
    /******************************************************************************
    * Helpers
    *****************************************************************************/
    static void
    purple_spasm_access_token_input_cb(gpointer data, const gchar *access_token) {
    - SpasmAccount *sa = data;
    + PurpleAccount *account = NULL;
    + PurpleConnection *connection = NULL;
    + PurpleSpasmAccount *sa = PURPLE_SPASM_ACCOUNT(data);
    - g_free(sa->access_token);
    - sa->access_token = (access_token) ? g_strdup(access_token) : NULL;
    + account = purple_spasm_account_get_account(sa);
    + purple_account_set_remember_password(account, TRUE);
    - purple_account_set_remember_password(sa->account, TRUE);
    - purple_account_set_password(sa->account, sa->access_token);
    + purple_spasm_account_set_access_token(sa, access_token);
    + purple_account_set_password(account, access_token);
    - purple_connection_set_state(sa->connection, PURPLE_CONNECTED);
    + connection = purple_spasm_account_get_connection(sa);
    + purple_connection_set_state(connection, PURPLE_CONNECTED);
    +
    + purple_spasm_refresh_user(sa);
    }
    static void
    purple_spasm_access_token_cancel_cb(gpointer data) {
    - SpasmAccount *sa = data;
    + PurpleSpasmAccount *sa = PURPLE_SPASM_ACCOUNT(data);
    +
    purple_connection_error(
    - sa->connection,
    + purple_spasm_account_get_connection(sa),
    "User cancelled authorization"
    );
    +
    + purple_spasm_account_free(sa);
    }
    /******************************************************************************
    @@ -54,19 +65,16 @@
    void
    purple_spasm_login(PurpleAccount *account) {
    PurpleConnection *pc = NULL;
    - SpasmAccount *sa = NULL;
    + PurpleSpasmAccount *sa = NULL;
    gchar *state = NULL, *uri = NULL;
    const gchar *username = NULL;
    pc = purple_account_get_connection(account);
    username = purple_account_get_username(account);
    - sa = g_new0(SpasmAccount, 1);
    + sa = purple_spasm_account_new(account, pc);
    purple_connection_set_protocol_data(pc, sa);
    - sa->account = account;
    - sa->connection = pc;
    -
    purple_connection_set_state(pc, PURPLE_CONNECTING);
    state = g_strdup_printf("%s,%s", PURPLE_SPASM_PLUGIN_ID, username);
    @@ -80,7 +88,7 @@
    );
    g_free(state);
    - purple_connection_update_progress(sa->connection, "Authenticating", 1, 2);
    + purple_connection_update_progress(pc, "Authenticating", 1, 2);
    /* send off the oauth implicit request */
    purple_notify_uri(pc, uri);
    @@ -97,7 +105,7 @@
    NULL,
    "OK", G_CALLBACK(purple_spasm_access_token_input_cb),
    "Cancel", G_CALLBACK(purple_spasm_access_token_cancel_cb),
    - sa->account,
    + account,
    NULL,
    NULL,
    sa
    --- a/spasm-const.h Thu May 04 23:13:55 2017 -0500
    +++ b/spasm-const.h Tue May 09 22:50:39 2017 -0500
    @@ -21,10 +21,12 @@
    #define PURPLE_SPASM_CONSTS_H
    #define PURPLE_SPASM_PLUGIN_ID "prpl-grim-spasm"
    +#define PURPLE_SPASM_BASE_URL "https://api.twitch.tv/kraken/"
    +#define PURPLE_SPASM_CONTENT_TYPE "application/vnd.twitchtv.v5+json"
    #define PURPLE_SPASM_OAUTH2_CLIENT_ID "w7le4wyxwbipv6kf5qmqogwkqskl12"
    #define PURPLE_SPASM_OAUTH2_SCOPES "user_read chat_login"
    #define PURPLE_SPASM_OAUTH2_REDIRECT_URI "https://pidgin.im/oauth.html"
    -#define PURPLE_SPASM_OAUTH2_URI "https://api.twitch.tv/kraken/oauth2/authorize?" \
    +#define PURPLE_SPASM_OAUTH2_URI PURPLE_SPASM_BASE_URL "oauth2/authorize?" \
    "response_type=token&" \
    "client_id=%s&" \
    "redirect_uri=%s&" \
    --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/spasm-rest.c Tue May 09 22:50:39 2017 -0500
    @@ -0,0 +1,123 @@
    +/*
    + * PurpleSpasm - A Twitch Protocol Plugin
    + * Copyright (C) 2017 Gary Kramlich <grim@reaperworld.com>
    + *
    + * This program is free software; you can redistribute it and/or
    + * modify it under the terms of the GNU General Public License
    + * as published by the Free Software Foundation; either version 2
    + * of the License, or (at your option) any later version.
    + *
    + * This program is distributed in the hope that it will be useful,
    + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    + * GNU General Public License for more details.
    + *
    + * You should have received a copy of the GNU General Public License
    + * along with this program; if not, write to the Free Software
    + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
    + */
    +
    +#include <libsoup/soup.h>
    +
    +#include "spasm-const.h"
    +#include "spasm-rest.h"
    +
    +/******************************************************************************
    + * Types
    + *****************************************************************************/
    +typedef struct {
    + PurpleSpasmAccount *sa;
    + PurpleSpasmRestCallback cb;
    + gpointer data;
    +} PurpleSpasmRestCallbackData;
    +
    +/******************************************************************************
    + * Callbacks
    + *****************************************************************************/
    +static void
    +_purple_spasm_request_request_cb(GObject *obj, GAsyncResult *res,
    + gpointer data)
    +{
    + GInputStream *istream = NULL;
    + GError *error = NULL;
    + JsonParser *parser = NULL;
    + PurpleSpasmRestCallbackData *cb_data = (PurpleSpasmRestCallbackData *)data;
    +
    + istream = soup_session_send_finish(SOUP_SESSION(obj), res, &error);
    + if(error) {
    + cb_data->cb(cb_data->sa, NULL, error, cb_data->data);
    +
    + g_free(cb_data);
    +
    + return;
    + }
    +
    + parser = json_parser_new();
    + json_parser_load_from_stream(parser, istream, NULL, &error);
    + if(error) {
    + cb_data->cb(cb_data->sa, NULL, error, cb_data->data);
    +
    + g_free(cb_data);
    +
    + return;
    + }
    +
    + cb_data->cb(cb_data->sa, parser, NULL, cb_data->data);
    +}
    +
    +/******************************************************************************
    + * API
    + *****************************************************************************/
    +void
    +purple_spasm_rest_request(PurpleSpasmAccount *sa, const gchar *method,
    + const gchar *path, const gchar *body,
    + PurpleSpasmRestCallback callback, gpointer data)
    +{
    + PurpleSpasmRestCallbackData *cb;
    + SoupMessage *msg = NULL;
    + SoupSession *session = NULL;
    + gchar *url = NULL, *auth = NULL;
    +
    + g_return_if_fail(sa);
    +
    + url = g_build_filename(PURPLE_SPASM_BASE_URL, path, NULL);
    + msg = soup_message_new(method, url);
    + g_free(url);
    +
    + // Set the Client-ID header
    + soup_message_headers_replace(
    + msg->request_headers,
    + "Client-ID",
    + PURPLE_SPASM_OAUTH2_CLIENT_ID
    + );
    +
    + // Set the Accept header
    + soup_message_headers_replace(
    + msg->request_headers,
    + "Accept",
    + PURPLE_SPASM_CONTENT_TYPE
    + );
    +
    + // Set the authorization header to the access token
    + auth = g_strdup_printf("OAuth %s", purple_spasm_account_get_access_token(sa));
    + soup_message_headers_replace(
    + msg->request_headers,
    + "Authorization", auth
    + );
    + g_free(auth);
    +
    + cb = g_new0(PurpleSpasmRestCallbackData, 1);
    + cb->sa = sa;
    + cb->cb = callback;
    + cb->data = data;
    +
    + session = purple_spasm_account_get_session(sa);
    + soup_session_send_async(
    + session,
    + msg,
    + NULL,
    + _purple_spasm_request_request_cb,
    + cb
    + );
    + g_object_unref(G_OBJECT(session));
    +}
    --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/spasm-rest.h Tue May 09 22:50:39 2017 -0500
    @@ -0,0 +1,37 @@
    +/*
    + * PurpleSpasm - A Twitch Protocol Plugin
    + * Copyright (C) 2017 Gary Kramlich <grim@reaperworld.com>
    + *
    + * This program is free software; you can redistribute it and/or
    + * modify it under the terms of the GNU General Public License
    + * as published by the Free Software Foundation; either version 2
    + * of the License, or (at your option) any later version.
    + *
    + * This program is distributed in the hope that it will be useful,
    + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    + * GNU General Public License for more details.
    + *
    + * You should have received a copy of the GNU General Public License
    + * along with this program; if not, write to the Free Software
    + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
    + */
    +
    +#ifndef PURPLE_SPASM_REST_H
    +#define PURPLE_SPASM_REST_H
    +
    +#include <glib.h>
    +
    +#include <json-glib/json-glib.h>
    +
    +#include "spasm-account.h"
    +
    +G_BEGIN_DECLS
    +
    +typedef void (*PurpleSpasmRestCallback)(PurpleSpasmAccount *sa, JsonParser *parser, GError *error, gpointer data);
    +
    +void purple_spasm_rest_request(PurpleSpasmAccount *sa, const gchar *method, const gchar *path, const gchar *body, PurpleSpasmRestCallback callback, gpointer data);
    +
    +G_END_DECLS
    +
    +#endif /* PURPLE_SPASM_USER_H */
    --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/spasm-user.c Tue May 09 22:50:39 2017 -0500
    @@ -0,0 +1,66 @@
    +/*
    + * PurpleSpasm - A Twitch Protocol Plugin
    + * Copyright (C) 2017 Gary Kramlich <grim@reaperworld.com>
    + *
    + * This program is free software; you can redistribute it and/or
    + * modify it under the terms of the GNU General Public License
    + * as published by the Free Software Foundation; either version 2
    + * of the License, or (at your option) any later version.
    + *
    + * This program is distributed in the hope that it will be useful,
    + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    + * GNU General Public License for more details.
    + *
    + * You should have received a copy of the GNU General Public License
    + * along with this program; if not, write to the Free Software
    + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
    + */
    +
    +#include <json-glib/json-glib.h>
    +
    +#include "debug.h"
    +
    +#include "spasm-user.h"
    +#include "spasm-rest.h"
    +
    +/******************************************************************************
    + * User endpoint
    + *****************************************************************************/
    +static void
    +_purple_spasm_refresh_user_cb(PurpleSpasmAccount *sa, JsonParser *parser,
    + GError *error, gpointer data)
    +{
    + JsonNode *node = NULL;
    +
    + if(error) {
    + purple_debug_info("spasm", "refresh user error: %s", error->message);
    +
    + g_error_free(error);
    +
    + return;
    + }
    +
    + node = json_parser_get_root(parser);
    +
    + // now output the string to make sure it's all working
    + JsonGenerator *gen = json_generator_new();
    + json_generator_set_root(gen, node);
    + json_generator_set_pretty(gen, TRUE);
    + gchar *json_data = json_generator_to_data(gen, NULL);
    + purple_debug_info("spasm", "%s", json_data);
    + g_free(json_data);
    + g_object_unref(G_OBJECT(gen));
    +}
    +
    +void
    +purple_spasm_refresh_user(PurpleSpasmAccount *sa) {
    + purple_spasm_rest_request(
    + sa,
    + "GET",
    + "/user",
    + NULL,
    + _purple_spasm_refresh_user_cb,
    + NULL
    + );
    +}
    --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/spasm-user.h Tue May 09 22:50:39 2017 -0500
    @@ -0,0 +1,33 @@
    +/*
    + * PurpleSpasm - A Twitch Protocol Plugin
    + * Copyright (C) 2017 Gary Kramlich <grim@reaperworld.com>
    + *
    + * This program is free software; you can redistribute it and/or
    + * modify it under the terms of the GNU General Public License
    + * as published by the Free Software Foundation; either version 2
    + * of the License, or (at your option) any later version.
    + *
    + * This program is distributed in the hope that it will be useful,
    + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    + * GNU General Public License for more details.
    + *
    + * You should have received a copy of the GNU General Public License
    + * along with this program; if not, write to the Free Software
    + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
    + */
    +
    +#ifndef PURPLE_SPASM_USER_H
    +#define PURPLE_SPASM_USER_H
    +
    +#include <glib.h>
    +
    +#include "spasm-account.h"
    +
    +G_BEGIN_DECLS
    +
    +void purple_spasm_refresh_user(PurpleSpasmAccount *sa);
    +
    +G_END_DECLS
    +
    +#endif /* PURPLE_SPASM_USER_H */