1
+ # Description:
2
+ # Manage your links and bookmarks. Links get stored in the robot brain while
3
+ # bookmarks get stored at pinboard.in. Also keeps a history of all URLs in
4
+ # the "urls" section of the robot brain.
5
+ #
6
+ # Dependencies:
7
+ # "xml2js": "0.1.14"
8
+ #
9
+ # Configuration:
10
+ # PINBOARD_USERNAME
11
+ # PINBOARD_PASSWORD
12
+ #
13
+ # Commands:
14
+ # hubot pin <url> as <description> - add a url to your pinboard feed
15
+ # hubot link <url> as <description> - add a url to the robot brain
16
+ # hubot link me for <description> - find a link by description
17
+ # hubot list bookmarks - get a list of the 15 most recent bookmarks
18
+ # hubot list links - List all of the links that are being tracked
19
+ # hubot feed me - get the URL to subscribe to your bookmark rss
20
+ #
21
+ # Author
22
+ # pezholio (based on work by mm53bar)
23
+
24
+ module .exports = (robot ) ->
25
+ robot .respond / feed me/ i , (msg ) ->
26
+ msg .reply " You can subscribe to the pinboard feed at https://feeds.pinboard.in/rss/u:#{ process .env .PINBOARD_USERNAME } /"
27
+
28
+ robot .respond / list bookmarks/ i , (msg ) ->
29
+ pinboard = new Pinboard msg, process .env .PINBOARD_USERNAME , process .env .PINBOARD_PASSWORD
30
+
31
+ pinboard .listBookmarks (err, message) ->
32
+ if err?
33
+ msg .send " #{ err} "
34
+ else
35
+ msg .send " #{ message} "
36
+
37
+ robot .respond / pin (http(s? )\:\/\/ \S + ) as (. + )/ i , (msg ) ->
38
+ pinboard = new Pinboard msg, process .env .PINBOARD_USERNAME , process .env .PINBOARD_PASSWORD
39
+ url = msg .match [1 ]
40
+ description = msg .match [3 ]
41
+ bookmark = new Bookmark url, description
42
+
43
+ pinboard .createBookmark bookmark, (err , message ) ->
44
+ if err?
45
+ msg .send " #{ err} "
46
+ else
47
+ msg .send " #{ message} "
48
+
49
+ robot .respond / link (http(s? )\:\/\/ \S + ) as (. + )/ i , (msg ) ->
50
+ url = msg .match [1 ]
51
+ description = msg .match [3 ]
52
+ bookmark = new Bookmark url, description
53
+ link = new Link robot
54
+
55
+ link .add bookmark, (err , message ) ->
56
+ if err?
57
+ msg .reply " I have a vague memory of hearing about that link sometime in the past."
58
+ else
59
+ msg .reply " I've stuck that link into my robot brain."
60
+
61
+ robot .respond / link me for (. + )/ i , (msg ) ->
62
+ description = msg .match [1 ]
63
+ link = new Link robot
64
+
65
+ link .find description, (err , bookmark ) ->
66
+ if err?
67
+ msg .send " #{ err} "
68
+ else
69
+ msg .send bookmark .url
70
+
71
+ robot .respond / list links/ i , (msg ) ->
72
+ link = new Link robot
73
+
74
+ link .list (err, message) ->
75
+ if err?
76
+ msg .reply " Links? What links? I don't remember any links."
77
+ else
78
+ msg .reply message
79
+
80
+ robot .hear / (http(s? )\:\/\/ \S + )/ i , (msg ) ->
81
+ href = msg .match [1 ]
82
+ url = new Url robot
83
+
84
+ url .add href, (err , message ) ->
85
+ if err?
86
+ console .log " #{ href} : #{ err} "
87
+
88
+ # Classes
89
+
90
+ class Url
91
+ constructor : (robot ) ->
92
+ robot .brain .data .urls ?= []
93
+ @urls_ = robot .brain .data .urls
94
+
95
+ all : (url ) ->
96
+ if url
97
+ @urls_ .push url
98
+ else
99
+ @urls_
100
+
101
+ add : (url , callback ) ->
102
+ if url in @ all ()
103
+ callback " Url already exists"
104
+ else
105
+ @ all url
106
+ callback null , " Url added"
107
+
108
+ class Bookmark
109
+ constructor : (url , description ) ->
110
+ @url = url
111
+ @description = description
112
+
113
+ encodedUrl : ->
114
+ encodeURIComponent @url
115
+
116
+ encodedDescription : ->
117
+ encodeURIComponent @description
118
+
119
+ class Link
120
+ constructor : (robot ) ->
121
+ robot .brain .data .links ?= []
122
+ @links_ = robot .brain .data .links
123
+
124
+ all : (bookmark ) ->
125
+ if bookmark
126
+ @links_ .push bookmark
127
+ else
128
+ @links_
129
+
130
+ add : (bookmark , callback ) ->
131
+ result = []
132
+ @ all ().forEach (entry) ->
133
+ if entry
134
+ if entry .url is bookmark .url
135
+ result .push bookmark
136
+ if result .length > 0
137
+ callback " Bookmark already exists"
138
+ else
139
+ @ all bookmark
140
+ callback null , " Bookmark added"
141
+
142
+ list : (callback ) ->
143
+ if @ all ().length > 0
144
+ resp_str = " These are the links I'm remembering:\n\n "
145
+ for bookmark in @ all ()
146
+ if bookmark
147
+ resp_str += bookmark .description + " (" + bookmark .url + " )\n "
148
+ callback null , resp_str
149
+ else
150
+ callback " No bookmarks exist"
151
+
152
+ find : (description , callback ) ->
153
+ result = []
154
+ @ all ().forEach (bookmark) ->
155
+ if bookmark && bookmark .description
156
+ if RegExp (description, " i" ).test bookmark .description
157
+ result .push bookmark
158
+ if result .length > 0
159
+ callback null , result[0 ]
160
+ else
161
+ callback " No results found"
162
+
163
+ class Pinboard
164
+ constructor : (msg , user , password ) ->
165
+ @msg = msg
166
+ @user = user
167
+ @password = password
168
+
169
+ feed_url : ->
170
+ " https://feeds.pinboard.in/rss/u:#{ @user } /"
171
+
172
+ authdata : ->
173
+ new Buffer (@user + ' :' + @password ).toString (' base64' )
174
+
175
+ createBookmark : (bookmark , callback ) ->
176
+ api_url = " https://api.pinboard.in/v1/posts/add?" +
177
+ " url=#{ bookmark .encodedUrl ()} " +
178
+ " &description=#{ bookmark .encodedDescription ()} "
179
+ @ getPinboard api_url, (err , data ) ->
180
+ if err? or not data?
181
+ callback err
182
+ else
183
+ resultRegexp = / result code="(. + )"/ i
184
+ result = data .match (resultRegexp)[1 ]
185
+ if result == ' done'
186
+ callback null , " Your bookmark was added to pinboard."
187
+ else
188
+ callback " There was a problem adding your bookmark to pinboard: #{ result} "
189
+
190
+ listBookmarks : (callback ) ->
191
+ xml2js = require (' xml2js' )
192
+ api_url = " https://api.pinboard.in/v1/posts/recent"
193
+ @ getPinboard api_url, (err , data ) ->
194
+ if err? or not data?
195
+ callback err
196
+ else
197
+ resp_str = " My bookmarks: \n "
198
+ (new xml2js.Parser ()).parseString data, (err , json )->
199
+ for post in json .posts .post
200
+ resp_str += post[" $" ].description + " (" + post[" $" ].href + " )\n "
201
+ callback null , resp_str
202
+
203
+ getPinboard : (api_url , callback ) ->
204
+ @msg .http (api_url).
205
+ header (' Authorization' , ' Basic ' + @ authdata ()).
206
+ get () (err , res , body ) ->
207
+ if res .statusCode is 200
208
+ callback null , body
209
+ else if err?
210
+ callback err
211
+ else
212
+ callback " There were problems contacting pinboard"
0 commit comments