From 6a430d8d1f79d5d699293f74c51217044ed03306 Mon Sep 17 00:00:00 2001 From: qorg11 Date: Fri, 23 Jul 2021 13:12:51 +0200 Subject: Added follow feature --- src/Makefile | 6 +- src/asprintf.c | 8 +-- src/asprintf.h | 4 +- src/follow.c | 164 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/follow.h | 5 ++ src/login.c | 14 ++--- src/main.c | 30 ++++++---- src/post.c | 4 +- src/upload_file.c | 4 +- 9 files changed, 208 insertions(+), 31 deletions(-) create mode 100644 src/follow.c create mode 100644 src/follow.h diff --git a/src/Makefile b/src/Makefile index e0dc9ae..c74d14e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,13 +1,13 @@ # demiurge makefile TARGET = demiurge -OBJS = login.o util.o post.o main.o upload_file.o +OBJS = login.o util.o post.o main.o upload_file.o asprintf.o follow.o CC = cc -CFLAGS = -O2 -MD -std=c11 -Wall -Wextra -lcurl -lreadline -ljson-c +CFLAGS += -O2 -MD -std=c11 -Wall -Wextra -lcurl -g -lreadline -ljson-c $(TARGET): $(OBJS) - $(CC) $(OBJS) $(CFLAGS) $(CFLAGSDEF) -o $(TARGET) + $(CC) $(OBJS) $(CFLAGS) -o $(TARGET) %.o: %.c $(CC) -c $(CFLAGS) $(CFLAGSDEF) $< -o $@ diff --git a/src/asprintf.c b/src/asprintf.c index 8026c52..ee01c2e 100644 --- a/src/asprintf.c +++ b/src/asprintf.c @@ -20,20 +20,20 @@ #include #include "asprintf.h" -/* Implementation of asprintf() */ +/* Implementation of dm_asprintf() */ int -asprintf(char **restrict strp, const char *restrict fmt, ...) +dm_asprintf(char **restrict strp, const char *restrict fmt, ...) { va_list args; int size = 0; va_start(args, fmt); va_end(args); - return size = vasprintf(strp, fmt, args); + return size = dm_vasprintf(strp, fmt, args); } int -vasprintf(char **restrict strp, const char *restrict fmt, va_list ap) +dm_vasprintf(char **restrict strp, const char *restrict fmt, va_list ap) { va_list args; va_copy(args, ap); diff --git a/src/asprintf.h b/src/asprintf.h index 76f1f4f..fe26354 100644 --- a/src/asprintf.h +++ b/src/asprintf.h @@ -18,7 +18,7 @@ #include int -asprintf(char **restrict strp, const char *restrict fmt, ...); +dm_asprintf(char **restrict strp, const char *restrict fmt, ...); int -vasprintf(char **restrict strp, const char *restrict fmt, va_list ap); +dm_vasprintf(char **restrict strp, const char *restrict fmt, va_list ap); diff --git a/src/follow.c b/src/follow.c new file mode 100644 index 0000000..1339558 --- /dev/null +++ b/src/follow.c @@ -0,0 +1,164 @@ +/* + This file is part of demiurge. + + demiurge 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 3 of the License, or + (at your option) any later version. + + demiurge 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 demiurge. If not, see . +*/ + +#include +#include +#include +#include +#include "util.h" +#include "asprintf.h" + +char * +get_account_id(char *name) +{ + char instance[50]; + char client_id[50]; + char client_secret[50]; + char access_token[50]; + + get_tokens_from_file( + ".demiurgerc", instance, client_id, client_secret, access_token); + CURL *curl = curl_easy_init(); + if(curl == NULL) { + fprintf(stderr, "Error creating libcurl thing\n"); + return NULL; + } + char *api_url_fmt = "%s/api/v1/accounts/%s/"; + char *api_url; + dm_asprintf(&api_url, api_url_fmt, instance, name); + struct json_object *parsed_json; + struct json_object *account_id; + + /* For some reason I don't understand, you can't get users remote + users withotu authorization. So I have to pass the + authorization header. */ + + char *header_fmt = "Authorization: Bearer %s"; + char *authorization_header = NULL; + struct curl_slist *header_list = NULL; + + dm_asprintf(&authorization_header, header_fmt, access_token); + header_list = curl_slist_append(header_list, authorization_header); + + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list); + + /* Curl options */ + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list); + curl_easy_setopt(curl, CURLOPT_URL, api_url); + /* Create buffer for the result */ + + struct memory chunk = { 0 }; + + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, cb); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk); + + /* free */ + + curl_easy_perform(curl); + curl_easy_cleanup(curl); + free(api_url); + free(authorization_header); + curl_slist_free_all(header_list); + /* parse the thing */ + + parsed_json = json_tokener_parse(chunk.response); + json_object_object_get_ex(parsed_json, "id", &account_id); + + /* keep freeing */ + char *str = (char *)json_object_get_string(account_id); + char *return_str = malloc(strlen(str + 1)); + strcpy(return_str, str); // strdup() segfaults for some reason + json_object_put(parsed_json); + free(chunk.response); + return return_str; +} + +int +follow_account(char *id) +{ + char instance[50]; + char client_id[50]; + char client_secret[50]; + char access_token[50]; + get_tokens_from_file( + ".demiurgerc", instance, client_id, client_secret, access_token); + CURL *curl = curl_easy_init(); + if(curl == NULL) { + fprintf(stderr, "Error creating libcurl thing\n"); + return -1; + } + char *api_url_fmt = "%s/api/v1/accounts/%s/follow"; + char *api_url; + dm_asprintf(&api_url, api_url_fmt, instance, id); + + char *header_fmt = "Authorization: Bearer %s"; + char *authorization_header = NULL; + struct curl_slist *header_list = NULL; + + dm_asprintf(&authorization_header, header_fmt, access_token); + header_list = curl_slist_append(header_list, authorization_header); + + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list); + curl_easy_setopt(curl, CURLOPT_POST, 1L); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, ""); + curl_easy_setopt(curl, CURLOPT_URL, api_url); + curl_easy_perform(curl); + curl_easy_cleanup(curl); + + curl_slist_free_all(header_list); + return 0; +} + +/* TODO: merge */ + +int +unfollow_account(char *id) +{ + char instance[50]; + char client_id[50]; + char client_secret[50]; + char access_token[50]; + get_tokens_from_file( + ".demiurgerc", instance, client_id, client_secret, access_token); + CURL *curl = curl_easy_init(); + if(curl == NULL) { + fprintf(stderr, "Error creating libcurl thing\n"); + return -1; + } + char *api_url_fmt = "%s/api/v1/accounts/%s/unfollow"; + char *api_url; + dm_asprintf(&api_url, api_url_fmt, instance, id); + + char *header_fmt = "Authorization: Bearer %s"; + char *authorization_header = NULL; + struct curl_slist *header_list = NULL; + + dm_asprintf(&authorization_header, header_fmt, access_token); + header_list = curl_slist_append(header_list, authorization_header); + + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list); + curl_easy_setopt(curl, CURLOPT_POST, 1L); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, ""); + curl_easy_setopt(curl, CURLOPT_URL, api_url); + curl_easy_perform(curl); + /* free */ + free(api_url); + free(authorization_header); + curl_easy_cleanup(curl); + curl_slist_free_all(header_list); + return 0; +} diff --git a/src/follow.h b/src/follow.h new file mode 100644 index 0000000..9e9bb2b --- /dev/null +++ b/src/follow.h @@ -0,0 +1,5 @@ +char * +get_account_id(char *name); + +int +follow_account(char *id); diff --git a/src/login.c b/src/login.c index 44d4866..e60b1f0 100644 --- a/src/login.c +++ b/src/login.c @@ -68,7 +68,7 @@ setup() char *post_url = NULL; - asprintf(&post_url, "%s%s", instance, api_url); + dm_asprintf(&post_url, "%s%s", instance, api_url); curl_easy_setopt(curl, CURLOPT_URL, post_url); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); curl_easy_setopt(curl, CURLOPT_WRITEDATA, buf); @@ -80,7 +80,7 @@ setup() curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "client_name=demiurge&redirect_uris=urn:ietf:wg:oauth:2." - "0:oob&scope=read write"); + "0:oob&scope=read write follow"); curl_easy_perform(curl); curl_easy_cleanup(curl); @@ -97,14 +97,14 @@ setup() const char *client_secret = json_object_get_string(json_client_secret); char *fmt = "%s%sresonse_type=code&client_id=%s&redirect_uri=urn:ietf:wg:" - "oauth:2.0:oob&force_login&scope=read write"; + "oauth:2.0:oob&force_login&scope=read write follow"; api_url = "/oauth/authorize?"; free(post_url); post_url = NULL; - asprintf(&post_url, fmt, instance, api_url, client_id); + dm_asprintf(&post_url, fmt, instance, api_url, client_id); puts(post_url); curl = curl_easy_init(); @@ -114,17 +114,17 @@ setup() char *access_token_fmt = "client_id=%s&client_secret=%s&redirect_uri=urn:ietf:wg:oauth:2.0:" - "oob&grant_type=authorization_code&code=%s&scope=read write"; + "oob&grant_type=authorization_code&code=%s&scope=read write follow"; api_url = "/oauth/token"; char *post_token_url = NULL; - asprintf( + dm_asprintf( &post_token_url, access_token_fmt, client_id, client_secret, code); post_url = NULL; - asprintf(&post_url, "%s%s", instance, api_url); + dm_asprintf(&post_url, "%s%s", instance, api_url); curl_easy_setopt(curl, CURLOPT_URL, post_url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_token_url); diff --git a/src/main.c b/src/main.c index ab9794b..6e0d8c1 100644 --- a/src/main.c +++ b/src/main.c @@ -21,11 +21,13 @@ #include #include #include +#include #include "login.h" #include "util.h" #include "post.h" #include "upload_file.h" +#include "follow.h" /* prints usage */ @@ -47,7 +49,8 @@ main(int argc, char **argv) char *status = NULL; char *visibility = NULL; char *id_ptr = NULL; - + char *account_id = NULL; + int follow_flag = false; /* TODO: Support filename and visibility */ if(!isatty(0)) { @@ -62,17 +65,22 @@ main(int argc, char **argv) return -1; } - while((c = getopt(argc, argv, "s:v:F:")) != -1) { + while((c = getopt(argc, argv, "s:v:F:f:")) != -1) { switch(c) { - case 's': - status = optarg; - break; - case 'v': - visibility = optarg; - break; - case 'F': - upload_file(optarg, basename(optarg), &id_ptr); - break; + case 's': + status = optarg; + break; + case 'v': + visibility = optarg; + break; + case 'F': + upload_file(optarg, basename(optarg), &id_ptr); + break; + case 'f': + account_id = get_account_id(optarg); + follow_account(account_id); + free(account_id); + return 0; } } diff --git a/src/post.c b/src/post.c index 9e9273d..7994493 100644 --- a/src/post.c +++ b/src/post.c @@ -45,12 +45,12 @@ post_status(const char *status, const char *scope, const char *media_id) char *api_url = "/api/v1/statuses"; char *url = NULL; - asprintf(&url, "%s%s", instance, api_url); + dm_asprintf(&url, "%s%s", instance, api_url); char *header_fmt = "Authorization: Bearer %s"; char *authorization_header = NULL; struct curl_slist *header_list = NULL; - asprintf(&authorization_header, header_fmt, access_token); + dm_asprintf(&authorization_header, header_fmt, access_token); header_list = curl_slist_append(header_list, authorization_header); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list); diff --git a/src/upload_file.c b/src/upload_file.c index 88de19f..c223efa 100644 --- a/src/upload_file.c +++ b/src/upload_file.c @@ -45,7 +45,7 @@ upload_file(const char *path, const char *description, char **id_ptr) curl_easy_setopt(curl, CURLOPT_WRITEDATA, buf); char *url_to_post = NULL; - asprintf(&url_to_post, "%s/api/v1/media", instance); + dm_asprintf(&url_to_post, "%s/api/v1/media", instance); /* Don't repeat yourself, so they say, it's the root of all evil * today */ @@ -53,7 +53,7 @@ upload_file(const char *path, const char *description, char **id_ptr) char *header_fmt = "Authorization: Bearer %s"; struct curl_slist *header_list = NULL; char *authorization_header = NULL; - asprintf(&authorization_header, header_fmt, access_token); + dm_asprintf(&authorization_header, header_fmt, access_token); header_list = curl_slist_append(header_list, authorization_header); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list); -- cgit v1.2.3