Skip to content

Commit

Permalink
v 3.0.0
Browse files Browse the repository at this point in the history
Версия 3.0.0
  • Loading branch information
selesnow committed Jan 15, 2021
1 parent b6c6673 commit 0e3d823
Show file tree
Hide file tree
Showing 70 changed files with 2,608 additions and 1,485 deletions.
3 changes: 3 additions & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
^.*\.Rproj$
^\.Rproj\.user$
vk_auth\.rds$
21 changes: 13 additions & 8 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
Package: rvkstat
Type: Package
Title: Interface to API 'vk.com'
Version: 2.6.2
Date: 2019-07-26
Title: R Interface to API 'vk.com'
Version: 3.0.0
Date: 2021-01-14
Author: Alexey Seleznev
Maintainer: Alexey Seleznev <[email protected]>
Description: Load data from vk.com api about your communiti users and views,
ads performance, post on user wall and etc. For more detail see
<https://vk.com/dev/first_guide>.
ads performance, post on user wall and etc. For more information
see API Documentation <https://vk.com/dev/first_guide>.
License: GPL-2
Depends: R (>= 3.5.0)
Imports: RCurl, jsonlite, httr, tidyr
Imports: dplyr (>= 1.0.0),
tidyr (>= 1.0.0),
jsonlite,
httr,
stringr,
lgr
Language: ru
Encoding: UTF-8
BugReports: https://github.com/selesnow/rvkstat/issues
URL: http://selesnow.github.io/rvkstat
License: GPL-2
URL: https://selesnow.github.io/rvkstat/
License: GPL-2
32 changes: 21 additions & 11 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# rvkstat function
export(vkAuth)
export(vkGetToken)
export(vkGetGroupToken)
Expand Down Expand Up @@ -25,16 +26,25 @@ export(vkGetDbCountries)
export(vkGetDbCities)
export(vkGetDbRegions)
export(vkGetUserFriends)
export(vkGetUserDialogs)
export(vkGetUserGroups)
export(vkGetUserWall)
export(vkLoadToken)
importFrom(utils,browseURL)
importFrom(httr,GET)
importFrom(httr,stop_for_status)
importFrom(httr,content)
importFrom(RCurl,getURL)
importFrom(jsonlite,fromJSON)
importFrom(jsonlite,toJSON)
importFrom(tidyr,separate)
import(tidyr)
export(vkSetUsername)
export(vkSetAccountId)
export(vkSetAgencyId)
export(vkSetAccessToken)
export(vkSetTokenPath)
export(vkSetThreshold)

# import from other package function
importFrom(httr,GET, stop_for_status, content)
importFrom(jsonlite,fromJSON, toJSON)
importFrom(tidyr, separate, unnest_longer, unnest_wider, tibble, replace_na)
importFrom(utils, browseURL, head, setTxtProgressBar, txtProgressBar)
importFrom(stringr, str_interp, str_glue)

# import package
import(dplyr)
import(lgr)

# S3 methods
S3method(print, vk_auth)
32 changes: 32 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# 3.0.0

Дата релиза: 2021-01-14

Большое обновление пакета, которое коснулось совершенно всех функций:

* Пакет переведён на работу с API Вконтакте версии 5.126
* В пакет теперь вшито приложение для работы с API Вконтакте, но вы по прежнему можете использовать созданные вами приложения.
* Функция `vkAuth()` теперь может кешировать полученные учётные данные в локальный файл. Т.е. теперь нет необходимости хранить токены в виде текста в коде.
* Пакет поддерживает опции и переменные среды для определеня пользователя, аккаунта, агентского аккаунта, версии API, токена, пути к учётным данным, id приложения для работы с API.
* В пакет добавлено семейство функций `vkSet*()`, которые упрощают установку опций пакета.
* В `rvkstat` был добавлен логгер, на данный момент он выводит не так много информации, но в будущем будет более функционален, управлять уровнем детализации можно с помощью функции `vkSetThreshold()`.
* У всех функций 4 последние аргумента теперь: `username`, `api_version`, `token_path`, `access_token`. При этом нет необходимости указывать версию API и токен. Лучшей практикой считается задать с помощью опций `rvkstat.username` и `rvkstat.token_path` логин пользователя под которым вы прошли авторизацию, и путь к папаке в которой хранятся учётные данные.
* В функции `vkGetAdCategories()` появился дополнительный аргумент `version`, который позволяет указать какую версию справочника вы хотите получить, указав `v1` вы получите справочник категорий с включающий устаревшие тематики, указав `v2` вы получите справочник включающий только актуальные категории.
* Изменился набор аргументов и результат в функциях: `vkGetGroupStatGenderAge()`.
* Большинство функций не именило свой интерфейс, но при этом мог изменится итоговый результат который возвращает функция, это связанно с изменениями которые были внедрены ща последний год в API Вконтакте.
* Из пакета была удалена функция `vkGetUserDialogs()` в связи с тем, что она использовала утаревший метод API, работа которого боле ене поддерживается.
* Во всех функциях был оптимизирован процесс парсинга результата, он был полностью переписан с циклов на функции `unnest_longer()` и `unnest_wider()` из пакета `tidyr`. Это добавило пакету дополнительные зависимости, но оптимизировало скорость парсинга результата.
* Из пакета удалена устаревшая зависимость с пакетом `RCurl`, который использовался в самых ранних функциях пакета. Теперь во всех функциях для отправки запросов используется пакет `httr`.
* В функциях из семейства `vkGetGroupStat*()` добавлено 2 новые аргумента: `interval`, `intervals_count`. Данные аргументы позволяют запрашивать данные за условный период.
* В документацию по каждой функции добавлен блок references, с ссылкой на документацию по API методу который лежит в основе функции.

---

# 2.6.1

Дата релиза: 2019-12-11

Доработана основная функция для загрузки статистики рекламны `vkGetAdStatistics()`:

* В результате который вы получаете с помощью данной функции добавлено поле lead_form_sends, количество полученных лид форм по вашей рекламе.
* Увеличена пауза между отправляемыми запросами т.к. Вконтакте усилил лимиты на количество отправляемых в API запросов.
Binary file modified R/sysdata.rda
Binary file not shown.
97 changes: 93 additions & 4 deletions R/vkAuth.R
Original file line number Diff line number Diff line change
@@ -1,11 +1,100 @@
vkAuth <- function(app_id = 5344605, app_secret = "CAyGdHhdgEBEW8fJCmzS", apiVersion = "5.68"){

browseURL(paste0("https://oauth.vk.com/authorize?client_id=",app_id,"&redirect_uri=https://selesnow.github.io/rvkstat/getCode/get_code.html&display=popup&scope=offline,groups,ads,stats&response_type=code&v=",apiVersion))
vkAuth <- function(
username = getOption("rvkstat.username"),
app_id = getOption("rvkstat.app_id"),
app_secret = getOption("rvkstat.app_secret"),
api_version = getOption("rvkstat.api_version"),
token_path = vkTokenPath(),
reauth = FALSE,
skip_option = FALSE)
{

# full path to file
access_path <- file.path(token_path, paste(username, "vk_auth.rds", sep = "."))

# check options
if ( ! is.null(getOption( "rvkstat.access_token" )) && !skip_option ) {

lg$debug("Access token was setted by option, if you want set new access token use skip_options = TRUE.")
return( getOption( "rvkstat.access_token" ) )

}

# check environ variables
if ( Sys.getenv("VK_API_TOKEN") != "" && !skip_option ) {

lg$debug("Access token was setted from environment variables, if you want set new access token use skip_options = TRUE.")
return( Sys.getenv("RVK_API_TOKEN") )

}

# check cach file
if ( file.exists( access_path ) && !reauth ) {

accessCredentilas <- readRDS(access_path)
lg$debug("Token load from %s", access_path)

} else {

# #############################
# open browser for auth
browseURL(paste0("https://oauth.vk.com/authorize?client_id=",app_id,"&redirect_uri=https://selesnow.github.io/rvkstat/getCode/get_code.html&display=popup&scope=offline,groups,ads,stats&response_type=code&v=",api_version))

# wait code
code <- readline(prompt = "Enter code from URL: ")


# get token
token <- GET(paste0("https://oauth.vk.com/access_token?client_id=",app_id,"&client_secret=",app_secret,"&redirect_uri=https://selesnow.github.io/rvkstat/getCode/get_code.html&code=",code))
# check api answer
stop_for_status(token)
# parse credential
accessCredentilas <- content(token, "parsed", "application/json")



# ask fo cache
message(str_interp("Do you want save your access token into rds file ${access_path} for use it between R sessions ? "))
to_cash <- readline( str_interp("y / n (recmedation y) ?: ") )

# cache
if ( to_cash %in% tolower( c("y", "yes", "ok", "save") ) ) {

if ( !dir.exists(token_path) ) {

dir.create(token_path, recursive = T)

}

# save data to rds file
saveRDS(object = accessCredentilas,
file = access_path)

lg$info(str_interp("Token saved in %s", access_path))

}
}

# add token claas
class(accessCredentilas) <- "vk_auth"

# return
return(accessCredentilas)
}

# detect token path
vkTokenPath <- function() {

ifelse( is.null(getOption("rvkstat.token_path")),
getwd(),
getOption("rvkstat.token_path") )

}

# S3 print for token
print.vk_auth <- function (x, show_token = FALSE, ...) {

cat("Vkontakte API Token:\n")
cat("access_token:", ifelse(show_token, x$access_token, "<hidden>"), "\n")
cat("expires_in: ", x$expires_in, "\n")
cat("user_id: ", x$user_id)

}
24 changes: 24 additions & 0 deletions R/vkCheckLimit.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
vkCheckLimit <- function(
account_id,
access_token,
api_version
) {

answer <- GET("https://api.vk.com/method/ads.getFloodStats",
query = list(
account_id = account_id,
access_token = access_token,
v = api_version
))
stop_for_status(answer)
dataRaw <- content(answer, "parsed", "application/json")

if ( dataRaw$response$left < 5 ) {

cat("Flood limit pause!")
message("Sleeping for ",dataRaw$response$refresh + 1," seconds until queries limit will refresh...")
Sys.sleep(dataRaw$response$refresh + 1)

}

}
28 changes: 28 additions & 0 deletions R/vkCurrentAdAccount.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# function for detect account_id and client_id ----------------------------
vkCurrentAdAccount <- function() {

if ( is.null(getOption("rvkstat.agency_id")) ) {

return(getOption("rvkstat.account_id"))

} else {

return(getOption("rvkstat.agency_id"))

}

}

vkCurrentClientAccount <- function() {

if ( !is.null(getOption("rvkstat.agency_id")) ) {

return(getOption("rvkstat.account_id"))

} else {

return(NULL)

}

}
57 changes: 36 additions & 21 deletions R/vkGetAdAccounts.R
Original file line number Diff line number Diff line change
@@ -1,34 +1,49 @@
vkGetAdAccounts <- function(access_token = NULL,
api_version = NULL){
if(is.null(access_token)){
stop("Set access_token in options, is require.")
}
vkGetAdAccounts <- function(
username = getOption("rvkstat.username"),
api_version = getOption("rvkstat.api_version"),
token_path = vkTokenPath(),
access_token = getOption("rvkstat.access_token"))

api_version <- api_version_checker(api_version)
{

query <- paste0("https://api.vk.com/method/ads.getAccounts?v=",api_version,"&access_token=",access_token)
answer <- GET(query)
# auth
if ( is.null(access_token) ) {

if ( Sys.getenv("RVK_API_TOKEN") != "" ) {
access_token <- Sys.getenv("RVK_API_TOKEN")
} else {
access_token <- vkAuth(username = username,
token_path = token_path)$access_token
}
}

if ( class(access_token) == "vk_auth" ) {

access_token <- access_token$access_token

}

# send query
answer <- GET("https://api.vk.com/method/ads.getAccounts",
query = list(
v = api_version,
access_token = access_token
))

stop_for_status(answer)

# get answer
dataRaw <- content(answer, "parsed", "application/json")

# check for error
if(!is.null(dataRaw$error)){
stop(paste0("Error ", dataRaw$error$error_code," - ", dataRaw$error$error_msg))
}

# result
result <- data.frame(account_id = integer(0),
account_type = character(0),
account_status = character(0),
access_role = character(0))

# parsing
for(i in 1:length(dataRaw$response)){
result <- rbind(result,
data.frame(account_id = dataRaw$response[[i]]$account_id,
account_type = dataRaw$response[[i]]$account_type,
account_status = dataRaw$response[[i]]$account_status,
access_role = dataRaw$response[[i]]$access_role))}
# convert result to data frame
result <- tibble(items = dataRaw$response) %>%
unnest_wider("items")

# #############->
return(result)
}
Loading

0 comments on commit 0e3d823

Please sign in to comment.