grim/purple-spasm
Clone
Summary
Browse
Changes
Graph
We need to actually tell libpurple that we're connected
2017-05-18, Gary Kramlich
84e6281b1e00
We need to actually tell libpurple that we're connected
/*
* 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
"debug.h"
#include
"request.h"
#include
"spasm.h"
#include
"spasm-account.h"
#include
"spasm-chat.h"
#include
"spasm-const.h"
#include
"spasm-user.h"
/******************************************************************************
* Structs
*****************************************************************************/
struct
_PurpleSpasmAccount
{
PurpleAccount
*
account
;
PurpleConnection
*
connection
;
GCancellable
*
cancellable
;
SoupSession
*
session
;
gchar
*
access_token
;
gchar
*
display_name
;
gchar
*
id
;
gchar
*
name
;
gchar
*
type
;
gchar
*
bio
;
gchar
*
logo
;
gchar
*
email
;
gboolean
email_verified
;
gboolean
partnered
;
gboolean
twitter_connected
;
PurpleSpasmChatService
*
chat
;
};
/******************************************************************************
* Helpers
*****************************************************************************/
static
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
;
}
static
void
purple_spasm_account_free
(
PurpleSpasmAccount
*
sa
)
{
g_return_if_fail
(
sa
);
g_free
(
sa
->
access_token
);
purple_spasm_chat_service_free
(
sa
->
chat
);
g_free
(
sa
);
}
static
void
_purple_spasm_account_set_access_token
(
PurpleSpasmAccount
*
sa
,
const
gchar
*
access_token
)
{
g_return_if_fail
(
sa
);
sa
->
access_token
=
g_strdup
(
access_token
);
}
static
GError
*
_purple_spasm_account_update_profile
(
PurpleSpasmAccount
*
sa
,
JsonParser
*
parser
)
{
JsonNode
*
root
=
NULL
;
JsonObject
*
obj
=
NULL
;
const
gchar
*
str_attr
=
NULL
;
if
(
sa
==
NULL
)
{
return
g_error_new
(
PURPLE_SPASM_DOMAIN
,
0
,
"invalid spasm account"
);
}
root
=
json_parser_get_root
(
parser
);
obj
=
json_node_get_object
(
root
);
str_attr
=
json_object_get_string_member
(
obj
,
"display_name"
);
sa
->
display_name
=
g_strdup
(
str_attr
);
str_attr
=
json_object_get_string_member
(
obj
,
"_id"
);
sa
->
id
=
g_strdup
(
str_attr
);
str_attr
=
json_object_get_string_member
(
obj
,
"name"
);
sa
->
name
=
g_strdup
(
str_attr
);
str_attr
=
json_object_get_string_member
(
obj
,
"type"
);
sa
->
type
=
g_strdup
(
str_attr
);
str_attr
=
json_object_get_string_member
(
obj
,
"bio"
);
sa
->
bio
=
g_strdup
(
str_attr
);
str_attr
=
json_object_get_string_member
(
obj
,
"logo"
);
sa
->
logo
=
g_strdup
(
str_attr
);
str_attr
=
json_object_get_string_member
(
obj
,
"email"
);
sa
->
email
=
g_strdup
(
str_attr
);
sa
->
email_verified
=
json_object_get_boolean_member
(
obj
,
"email_verified"
);
sa
->
partnered
=
json_object_get_boolean_member
(
obj
,
"partnered"
);
sa
->
twitter_connected
=
json_object_get_boolean_member
(
obj
,
"twitter_connected"
);
return
NULL
;
}
/******************************************************************************
* Auth
*****************************************************************************/
static
void
_purple_spasm_oauth_login
(
PurpleSpasmAccount
*
sa
);
static
void
_purple_spasm_login_test_cb
(
PurpleSpasmAccount
*
sa
,
JsonParser
*
parser
,
GError
*
error
,
gpointer
data
)
{
PurpleAccount
*
account
=
NULL
;
PurpleConnection
*
connection
=
NULL
;
if
(
error
!=
NULL
)
{
purple_debug_info
(
"spasm"
,
"oauth token invalid, re-authenticating : %s
\n
"
,
error
->
message
);
_purple_spasm_oauth_login
(
sa
);
return
;
}
account
=
purple_spasm_account_get_account
(
sa
);
connection
=
purple_account_get_connection
(
account
);
error
=
_purple_spasm_account_update_profile
(
sa
,
parser
);
if
(
error
!=
NULL
)
{
gchar
*
err_msg
=
NULL
;
err_msg
=
g_strdup_printf
(
"failed to update profile : %s"
,
error
->
message
);
g_error_free
(
error
);
purple_connection_error
(
connection
,
err_msg
);
g_free
(
err_msg
);
return
;
}
sa
->
chat
=
purple_spasm_chat_service_new
(
sa
);
purple_spasm_chat_service_connect
(
sa
->
chat
);
}
static
void
_purple_spasm_access_token_input_cb
(
gpointer
data
,
const
gchar
*
access_token
)
{
PurpleAccount
*
account
=
NULL
;
PurpleConnection
*
connection
=
NULL
;
PurpleSpasmAccount
*
sa
=
PURPLE_SPASM_ACCOUNT
(
data
);
account
=
purple_spasm_account_get_account
(
sa
);
purple_account_set_remember_password
(
account
,
TRUE
);
_purple_spasm_account_set_access_token
(
sa
,
access_token
);
purple_account_set_password
(
account
,
access_token
);
connection
=
purple_spasm_account_get_connection
(
sa
);
purple_connection_update_progress
(
connection
,
"Verifying"
,
2
,
3
);
purple_spasm_get_user
(
sa
,
_purple_spasm_login_test_cb
,
NULL
);
}
static
void
_purple_spasm_access_token_cancel_cb
(
gpointer
data
)
{
PurpleSpasmAccount
*
sa
=
PURPLE_SPASM_ACCOUNT
(
data
);
purple_connection_error
(
purple_spasm_account_get_connection
(
sa
),
"User cancelled authorization"
);
purple_spasm_account_free
(
sa
);
}
static
void
_purple_spasm_oauth_login
(
PurpleSpasmAccount
*
sa
)
{
PurpleAccount
*
account
=
NULL
;
PurpleConnection
*
connection
=
NULL
;
gchar
*
state
=
NULL
,
*
uri
=
NULL
;
const
gchar
*
username
=
NULL
;
account
=
purple_spasm_account_get_account
(
sa
);
connection
=
purple_account_get_connection
(
account
);
purple_connection_update_progress
(
connection
,
"Authenticating"
,
1
,
3
);
username
=
purple_account_get_username
(
account
);
state
=
g_strdup_printf
(
"%s,%s"
,
PURPLE_SPASM_PLUGIN_ID
,
username
);
uri
=
g_strdup_printf
(
PURPLE_SPASM_OAUTH2_URI
,
PURPLE_SPASM_OAUTH2_CLIENT_ID
,
PURPLE_SPASM_OAUTH2_REDIRECT_URI
,
PURPLE_SPASM_OAUTH2_SCOPES
,
state
);
g_free
(
state
);
/* send off the oauth implicit request */
purple_notify_uri
(
connection
,
uri
);
g_free
(
uri
);
purple_request_input
(
connection
,
"Access Token"
,
"Enter the access token from https://pidgin.im/oauth.html which should have opened in your web browser"
,
NULL
,
"access token"
,
FALSE
,
TRUE
,
NULL
,
"OK"
,
G_CALLBACK
(
_purple_spasm_access_token_input_cb
),
"Cancel"
,
G_CALLBACK
(
_purple_spasm_access_token_cancel_cb
),
account
,
NULL
,
NULL
,
sa
);
}
/******************************************************************************
* API
*****************************************************************************/
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
;
}
GCancellable
*
purple_spasm_account_get_cancellable
(
const
PurpleSpasmAccount
*
sa
)
{
g_return_val_if_fail
(
sa
,
NULL
);
return
sa
->
cancellable
;
}
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
;
}
const
gchar
*
purple_spasm_account_get_access_token
(
const
PurpleSpasmAccount
*
sa
)
{
g_return_val_if_fail
(
sa
,
NULL
);
return
sa
->
access_token
;
}
const
gchar
*
purple_spasm_account_get_display_name
(
const
PurpleSpasmAccount
*
sa
)
{
g_return_val_if_fail
(
sa
,
NULL
);
return
sa
->
display_name
;
}
const
gchar
*
purple_spasm_account_get_id
(
const
PurpleSpasmAccount
*
sa
)
{
g_return_val_if_fail
(
sa
,
NULL
);
return
sa
->
id
;
}
const
gchar
*
purple_spasm_account_get_name
(
const
PurpleSpasmAccount
*
sa
)
{
g_return_val_if_fail
(
sa
,
NULL
);
return
sa
->
name
;
}
const
gchar
*
purple_spasm_account_get_type
(
const
PurpleSpasmAccount
*
sa
)
{
g_return_val_if_fail
(
sa
,
NULL
);
return
sa
->
type
;
}
const
gchar
*
purple_spasm_account_get_bio
(
const
PurpleSpasmAccount
*
sa
)
{
g_return_val_if_fail
(
sa
,
NULL
);
return
sa
->
bio
;
}
const
gchar
*
purple_spasm_account_get_logo
(
const
PurpleSpasmAccount
*
sa
)
{
g_return_val_if_fail
(
sa
,
NULL
);
return
sa
->
logo
;
}
const
gchar
*
purple_spasm_account_get_email
(
const
PurpleSpasmAccount
*
sa
)
{
g_return_val_if_fail
(
sa
,
NULL
);
return
sa
->
email
;
}
gboolean
purple_spasm_account_get_email_verified
(
const
PurpleSpasmAccount
*
sa
)
{
g_return_val_if_fail
(
sa
,
FALSE
);
return
sa
->
email_verified
;
}
gboolean
purple_spasm_account_get_partnered
(
const
PurpleSpasmAccount
*
sa
)
{
g_return_val_if_fail
(
sa
,
FALSE
);
return
sa
->
partnered
;
}
gboolean
purple_spasm_account_get_twitter_connected
(
const
PurpleSpasmAccount
*
sa
)
{
g_return_val_if_fail
(
sa
,
FALSE
);
return
sa
->
twitter_connected
;
}
void
purple_spasm_account_login
(
PurpleAccount
*
account
)
{
PurpleConnection
*
pc
=
NULL
;
PurpleSpasmAccount
*
sa
=
NULL
;
const
gchar
*
password
=
NULL
;
pc
=
purple_account_get_connection
(
account
);
sa
=
purple_spasm_account_new
(
account
,
pc
);
purple_connection_set_protocol_data
(
pc
,
sa
);
purple_connection_set_state
(
pc
,
PURPLE_CONNECTING
);
/* try to load the password */
password
=
purple_account_get_password
(
account
);
if
(
password
!=
NULL
)
{
_purple_spasm_account_set_access_token
(
sa
,
password
);
purple_spasm_get_user
(
sa
,
_purple_spasm_login_test_cb
,
NULL
);
}
else
{
_purple_spasm_oauth_login
(
sa
);
}
}