-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.rkt
162 lines (142 loc) · 6.49 KB
/
main.rkt
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#lang racket/base
(require racket/contract
racket/string
racket/bool
net/http-easy)
;; エンドポイントURL
(define endpoint "https://versatileapi.herokuapp.com/api")
;; ユーザアカウントに関する情報を構造体で表現する。
(struct user
[id ;; ユーザアカウントのID(文字列)
created-at ;; ユーザアカウントの作成日時(ISO 8601形式)
updated-at ;; ユーザアカウントの更新日時(ISO 8601形式)
name ;; スクリーンネーム(文字列)
description] ;; 自己紹介(文字列)
#:transparent)
;; ユーザアカウント系APIから返ってくるオブジェクトをuserに変換する。
(define/contract (hash-to-user user#)
(-> hash-eq? user?)
(user (hash-ref user# 'id)
(hash-ref user# '_created_at)
(hash-ref user# '_updated_at)
(hash-ref user# 'name)
(hash-ref user# 'description)))
;; ユーザアカウントを作成する
(define/contract (sns-create-user name description)
(-> string? string? string?)
(let ([user# (response-json
(post (string-append endpoint "/user/create_user")
#:json (hasheq 'name name
'description description)))])
(hash-ref user# 'id)))
;; ユーザアカウントを更新する。
(define/contract (sns-update-user name description)
(-> string? string? string?)
(let ([user# (response-json
(put (string-append endpoint "/user/create_user")
#:json (hasheq 'name name
'description description)))])
(hash-ref user# 'id)))
;; SNS上に存在するユーザを全て取得する。
(define/contract (sns-get-all-users)
(-> (listof user?))
(let ([user#s (response-json
(get (string-append endpoint "/user/all")))])
(map hash-to-user user#s)))
;; 指定したユーザIDをもつユーザアカウントを取得する。
(define/contract (sns-get-user user-id)
(-> string? (or/c user? false?))
(let ([response (get (string-append endpoint "/user/" user-id))])
(if (= (response-status-code response) 200)
(hash-to-user (response-json response))
#f)))
;; 指定したユーザIDをもつユーザアカウントを取得する(キャッシュ付き)。
(define userdb (make-hash))
(define (sns-get-user* user-id)
;(-> string? user?)
(hash-ref! userdb user-id (lambda ()
(sns-get-user user-id))))
;; ツイートに関する情報を構造体で表現する。
(struct tweet
[id ;; ツイートID
user-id ;; ユーザID
created-at ;; 投稿された日時
updated-at ;; 更新された日時
text] ;; 本文
#:transparent)
;; SNSにツイートする。
(define/contract (sns-tweet text)
(-> string? string?)
(let ([response (post (string-append endpoint "/text")
#:headers (hasheq 'Authorization "HelloWorld")
#:json (hasheq 'text text))])
(if (= 201 (response-status-code response))
(hash-ref (response-json response) 'id)
(raise 'post-failed))))
;; ツイート系APIから返ってくるオブジェクトをtweetに変換する。
(define/contract (hash-to-tweet tweet#)
(-> hash-eq? tweet?)
(tweet (hash-ref tweet# 'id)
(hash-ref tweet# '_user_id)
(hash-ref tweet# '_created_at)
(hash-ref tweet# '_updated_at)
(hash-ref tweet# 'text)))
;; 指定されたツイートIDをもつツイートを取得する。
(define/contract (sns-get-tweet id)
(-> string? tweet?)
(let* ([response (get (string-append endpoint "/text/" id))]
[tweet# (response-json response)])
(hash-to-tweet tweet#)))
;; SNS上の全てのツイートを取得する。
(define/contract (sns-get-all-tweets)
(-> (listof tweet?))
(let ([user#s (response-json (get (string-append endpoint "/text/all")))])
(map hash-to-tweet user#s)))
;; ユーザIDのリストからスクリーンネームを割りだす
(module+ main
(require racket/cmdline)
(define cmd-operation (make-parameter null))
(define cmd-user-name (make-parameter null))
(define cmd-user-description (make-parameter ""))
(define cmd-text-to-tweet (make-parameter ""))
(command-line
#:program "esns"
#:once-any
[("-c" "--create-user") name description "Create user"
(begin (cmd-operation 'create-user)
(cmd-user-name name)
(cmd-user-description description))]
[("-u" "--update-user") name description "Update user"
(begin (cmd-operation 'create-user)
(cmd-user-name name)
(cmd-user-description description))]
[("-t" "--tweet") text "Tweet"
(begin (cmd-operation 'tweet)
(cmd-text-to-tweet text))]
[("-w" "--who-are-you") "List all users in SNS"
(begin (cmd-operation 'list-all-users))]
[("-l" "--list-all-tweets") "List all tweets in SNS"
(begin (cmd-operation 'list-all-tweets))]
#:args ()
(case (cmd-operation)
[(create-user) (printf "~a~n" (sns-create-user (cmd-user-name) (cmd-user-description)))]
[(update-user) (printf "~a~n" (sns-update-user (cmd-user-name) (cmd-user-description)))]
[(tweet) (if (non-empty-string? (cmd-text-to-tweet))
(printf "~a~n" (sns-tweet (cmd-text-to-tweet)))
(eprintf "empty text! specify something~n"))]
[(list-all-users) (for-each (lambda (user)
(printf "~a:~a~n"
(user-name user)
(user-description user)))
(sns-get-all-users))]
[(list-all-tweets) (for-each (lambda (tweet)
(printf "~a:~a:~a~n"
(let ([user (sns-get-user* (tweet-user-id tweet))])
(if (user? user)
(user-name user)
"<unavailable>"))
(tweet-created-at tweet)
(tweet-text tweet)))
(sns-get-all-tweets))]
[else (eprintf "see help using -h flag~n")]))
)