forked from ierton/vkhs
-
Notifications
You must be signed in to change notification settings - Fork 6
/
ARTICLE.txt
128 lines (95 loc) · 7.93 KB
/
ARTICLE.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
Данная заметка продолжает тему, поднятую пользователем <hh user="laughedelic"/> в
статье http://habrahabr.ru/post/85894 - разработку приложения Vkontakte,
используя язык программирования Haskell. Похоже, за два года в API социаьной
сети произошли изменения, коснувшиеся, главным образом, процеуры авторизации.
Описанный автором метод по-видимому можно считать устаревшим (хотя не
исключено что он всё ещё работает), поэтому я решил
написать библиотеку, следующую новым правилам, опубликованным в разделе для
разработчиков
http://vk.com/developers.php?oid=-1&p=Авторизация
Как сообщается по ссылке, авторизовываться можно целыми тремя способами, я
выбрал второй - т.н. Implicit flow, поскольку:
- именно этот способ позволяет получить доступ к самому полному набору функций
- в дальнейшем я планирую разработать standalone-приложение, работающее в
качестве демона
Итак, чтоже теперь требуется сделать программисту, чтобы смочь вызывать заветные
функции? Документация (http://vk.com/developers.php?oid=-1&p=Авторизация_клиентских_приложений) говорит о следующей последовательности действий:
1) Открытие окна браузера для аутентификации пользователя на сайте ВКонтакте.
2) Разрешение пользователем доступа к своим данным.
3) Передача в приложение ключа access_token для доступа к API.
Возможно, программисты, работающим в области разработки Web-приложений, не увидят ничего необычного, но у меня сразу появился вопрос: а что делать, если браузера, окно которого можно былобы открыть, нет, что если приложение работает, как я писал выше, в качестве демона на каком-нибудь сервере и общается с пользователем через терминал? Похоже такой вариант авторами API не рассматривался, поэтому всё что остается - заняться написанием робота.
К счастью, на Hackage есть все необходимые компоненты. В первую очередь, это
целых две обертки к libcurl: первая так и называется - curl и включает в себя
много дополнительных функций, таких как анализ cookie.
http://hackage.haskell.org/package/curl
вторая - более "тонкая" curlhs, ничего лишнего, даже кое-чего нехватает.
http://hackage.haskell.org/package/curlhs
Во-вторых - библиотека tagsoup (а также целый выводок её по-разному улучшенных клонов), позволяющая анализировать html, в частности, вырезать из него формы. Её особенность - очень простой интерйейс.
http://hackage.haskell.org/package/tagsoup
В-третьих - готовый программируемый робот shpider, которого я нашел не очень
удобным в использовании, но очень полезным, если заглянуть в его исходники.
http://hackage.haskell.org/package/shpider
Также мне потребовался парсер HTTP-заголовков. Можно было выбрать классичесций HTTP, однако так сложилось, что я воспользовался пакетоа salvia-protocol
http://hackage.haskell.org/package/salvia-protocol
Далее, нам потребуется иджентификатор приложения, который необходимо получить,
зарегистрировав название приложения на странице
http://vk.com/editapp?act=create
и пройдя процедуру активации по SMS
Как же устроен наш робот? в общем, его действия сводятся к тому, чтобы
перейдя в точку входа, получить ответ, выплнить действие, сводящееся либо к
прыжку на перенаправляемую страницу, либо к заполнению и отправке формы.
Повторять процедуру до получения перенаправления, содержащего параметр access_token, который и является ключем, необходимым для вызова API функций.
Приведу кусок псевдокода, очень похожего на настоящий:
<source lang="haskell">
type AccessToken = (String,String,String)
data Action = OpenUrl Uri Cookies | SendForm Form Cookies
deriving (Show)
-- ClientId - это и есть идентификатор приложения, полученный после
-- SMS-активации.
vk_start_action :: ClientId -> [AccessRight] -> Action
vk_start_action cid ac = OpenUrl start_url mempty where
start_url = (\f -> f $ toUri "http://oauth.vk.com/authorize")
$ set query $ bw params
[ ("client_id", cid)
, ("scope", toarg ac)
, ("redirect_uri", "http://oauth.vk.com/blank.html")
, ("display", "wap")
, ("response_type", "token")
]
vk_analyze :: (Page,Cookies) -> VK (Either AccessToken Action)
vk_analyze ((h,b),c)
| isJust a = return $ Left (fromJust a)
| isJust l = return $ Right $ OpenUrl (fromJust l) c
| (not . null) f = return $ Right $ SendForm (head f) c
| otherwise = fail "HTML processing failure (new design of VK login dialog?)"
where
l = get location h
f = parseTags >>> gatherForms $ b
a = uri_fragment h
vk_move :: Action -> VK (Page, Cookies)
vk_move (OpenUrl u c) = do
(h,b) <- (vk_get u c)
return ((h,b),c`mappend`(get setCookies h))
vk_move (SendForm f c) = do
f' <- vk_fill_form f
(h,b) <- (vk_post f' c)
return ((h,b),c`mappend`(get setCookies h))
login :: Env -> IO (Either String AccessToken)
login e = runVK e $ loop 0 (vk_start_action (clientId e) (ac_rights e))
where
loop n act = do
ans@(p,c) <- vk_move act
r <- vk_analyze ans
case r of
Right act' -> do
loop (n+1) act'
Left access -> do
return access
</source>
В результате выполнения программы выяснилось, что обычный процесс авторизации
занимает примерно 8 перенаправлений, на пути которых встречается одна или две
экранных формы, изображения которых и присутствуют в инструкции.
Весь код я оформил в виде библиотеки VKHS, которая доступна по ссылке
https://github.com/ierton/vkhs
а также на Hackage.
Надеюсь, кому-нибудь пригодиться.