HaskerDeux

Check-in [4af11b69a0]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Always reference cookie files from home dir; API url changes

I forgot to commit the cookie changes awhile back so they've got caught up in a commit fixing the API urls.

The cookie stuff just makes sense. Previously the cookie files were stored in the same directory we were running haskerdeux from, which could lead to multiple files. Makes sense to reference one location (home directory).

The API changes I found when this stopped working: https://atomicules.co.uk/2017/08/27/Remind-to-Teuxdeux.html

Which is friggin' annoying as I almost forgot about Mothering Sunday.

Anyway, it seems some of the URLs haven't so much changed, but now don't like trailing slashes in some cases.

- new, post, can't have trailing slash
- crossoff, put, needs trailing slash
- putoff, put, can't have trailing slash
- moveto, put, can't have trailing slash
- remove, delete, needs trailing slash

Yay for consistency!

Hmm... actually I might tweak this further on a following commit as the puts don't make sense to me.

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | origin/issue1 | trunk | master
Files: files | file ages | folders
SHA3-256: 4af11b69a008c4d2258983c63746c545302e49f96e9679e35e79650298e5f4c8
User & Date: atomicules 2020-03-14 15:09:11
Context
2020-03-14
15:15
Follow-up to previous commit - remove all trailing slashes from apiurls

And add to the put and delete where needed.

This is better and more consistent. Also works. Odd that things magically broke
before though. check-in: 06a6b89ac2 user: atomicules tags: origin/issue1, trunk, master

15:09
Always reference cookie files from home dir; API url changes

I forgot to commit the cookie changes awhile back so they've got caught up in a commit fixing the API urls.

The cookie stuff just makes sense. Previously the cookie files were stored in the same directory we were running haskerdeux from, which could lead to multiple files. Makes sense to reference one location (home directory).

The API changes I found when this stopped working: https://atomicules.co.uk/2017/08/27/Remind-to-Teuxdeux.html

Which is friggin' annoying as I almost forgot about Mothering Sunday.

Anyway, it seems some of the URLs haven't so much changed, but now don't like trailing slashes in some cases.

- new, post, can't have trailing slash
- crossoff, put, needs trailing slash
- putoff, put, can't have trailing slash
- moveto, put, can't have trailing slash
- remove, delete, needs trailing slash

Yay for consistency!

Hmm... actually I might tweak this further on a following commit as the puts don't make sense to me. check-in: 4af11b69a0 user: atomicules tags: origin/issue1, trunk, master

2019-02-08
12:52
Add comment for future list usage support check-in: 0fe877fd3b user: atomicules tags: origin/issue1, trunk, master
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to haskerdeux.hs.

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
...
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
...
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
		-- if entry is on multiple lines
		else (last $ words $ netrc' !! 1, last $ words $ netrc' !! 2)
		where getcred c = dropWhile (not . (c `isInfixOf`)) (words $ head netrc') !! 1
	return (username, password)


curlget (token, date) = do

	let curlheader = "X-CSRF-Token: " ++ token

	body <- readProcess "curl" ["-s", "-L", "-c", "haskerdeux.cookies", "-b", "haskerdeux.cookies", "-H", curlheader, "https://teuxdeux.com/api/v1/todos/calendar?begin_date="++date++"&end_date="++date] []
	let ok = not ("Invalid CSRF Token" `isInfixOf` body)
	if ok
		then do
			let tds = decodeJSON body :: [Teuxdeux]
			let tdsf = Data.List.filter (\td -> current_date td == date && not (done td)) tds
			return tdsf
		else do
			token <- relogin 
			curlget (token, date)
	

curlpost (token, [date, key, value, apiurl, okresponse]) number = do


	let curlheader = "X-CSRF-Token: " ++ token
	--Can be much improved, but will do for now:
	json <- if isJust number
		then do
			tdsf <- curlget (token, date)
			let itemid = Main.id $ tdsf!!(read (fromJust number)::Int)
			let modjson = "{ \"ids\" : [\""++show itemid++"\"], \""++key++"\" : \""++value++"\"}"
			return modjson
		else do
			--Can't just straight return these strings, need to let them first
			let newjson = "{ \"current_date\" : \""++date++"\", \""++key++"\" : \""++value++"\"}"
			return newjson
	body <- readProcess "curl" ["-s", "-XPOST", apiurl, "-L", "-c", "haskerdeux.cookies", "-b", "haskerdeux.cookies", "-H", curlheader, "-H", "Content-Type: application/json", "-d", json] []
	let ok = not ("Invalid CSRF Token" `isInfixOf` body)
	if ok
		then
			if "done_updated_at" `isInfixOf` body
				then putStrLn okresponse
				else putStrLn "Uh Oh! Didn't work!"
		else do
			token <- relogin 
			curlpost (token, [date, key, value, apiurl, okresponse]) number


curldelete (token, [date, apiurl, okresponse]) number = do


	tdsf <- curlget (token, date)
	let itemid = Main.id $ tdsf!!(read number::Int)
	let curlheader = "X-CSRF-Token: " ++ token
	body <- readProcess "curl" ["-s", "-XDELETE", apiurl++show itemid, "-c", "haskerdeux.cookies", "-b", "haskerdeux.cookies", "-H", curlheader] []
	let ok = not ("Invalid CSRF Token" `isInfixOf` body)
	if ok
		then
			if "done_updated_at" `isInfixOf` body
				then putStrLn okresponse
				else putStrLn "Uh Oh! Didn't work!"
		else do
			token <- relogin 
			curldelete (token, [date, apiurl, okresponse]) number


curlput (token, [date, json, apiurl, okresponse]) number = do


	tdsf <- curlget (token, date)
	let itemid = Main.id $ tdsf!!(read number::Int)
	let curlheader = "X-CSRF-Token: " ++ token
	body <- readProcess "curl" ["-s", "-XPUT", apiurl++show itemid, "-L", "-c", "haskerdeux.cookies", "-b", "haskerdeux.cookies", "-H", curlheader, "-H", "Content-Type: application/json", "-d", json] []
	let ok = not ("Invalid CSRF Token" `isInfixOf` body)
	if ok
		then
			if "done_updated_at" `isInfixOf` body
				then putStrLn okresponse
				else putStrLn "Uh Oh! Didn't work!"
		else do
................................................................................


login  = do
	username <- fmap fst readnetrc
	password <- fmap snd readnetrc
	home <- getHomeDirectory
	savedtoken <- doesFileExist (home ++ "/.haskerdeux-token")

	if savedtoken
		then do
			token <- readFile (home ++ "/.haskerdeux-token")
			return token
		else do
			body <- readProcess "curl" ["-s", "-L", "-c", "haskerdeux.cookies", "https://teuxdeux.com/login"] []
			token <- getauthtoken body
			writeFile (home ++ "/.haskerdeux-token") token
			let curlheader = "X-CSRF-Token: " ++ token
			let curlpostfields = "username=" ++ username ++ "&password=" ++ password ++ "&authenticity_token=" ++ token
			body <- readProcess "curl" ["-s", "-L", "-c", "haskerdeux.cookies", "-b", "haskerdeux.cookies", "-H", curlheader, "-d", curlpostfields, "https://teuxdeux.com/login"] []
			return token


relogin = do
	home <- getHomeDirectory
	removeFile (home ++ "/.haskerdeux-token")
	token <- login
................................................................................
todos (token, [todos_date]) = do
	tdsf <- curlget (token, todos_date)
	putStr $ unlines $ zipWith (\n td -> show n ++ " - " ++ td) [0..] $ Data.List.map text tdsf --numbering from LYAH


new (token, [todos_date, todo]) = do 
	let encodedtodo = Network.URI.Encode.encode todo
	curlpost (token, [todos_date, "text", todo, "https://teuxdeux.com/api/v1/todos/", "Added!"]) Nothing


crossoff (token, [todos_date, number]) =
	curlput (token, [todos_date, "{ \"done\": true }", "https://teuxdeux.com/api/v1/todos/", "Crossed Off!"]) number


putoff (token, [todos_date, number]) = do
	let tomorrows_date = show (addDays 1 $ read todos_date::Data.Time.Day)
	curlpost (token, [todos_date, "current_date", tomorrows_date, "https://teuxdeux.com/api/v1/todos/reposition/", "Put Off!"]) (Just number)


moveto (token, [todos_date, number, new_date]) =
	--TODO: Need to figure out moving to bottom of a list
	curlpost (token, [todos_date, "current_date", new_date, "https://teuxdeux.com/api/v1/todos/reposition", "Moved!"]) (Just number)









>

>
|












>
>












|












>
>



|












>
>



|







 







>





|




|







 







|








|







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
...
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
...
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
		-- if entry is on multiple lines
		else (last $ words $ netrc' !! 1, last $ words $ netrc' !! 2)
		where getcred c = dropWhile (not . (c `isInfixOf`)) (words $ head netrc') !! 1
	return (username, password)


curlget (token, date) = do
	home <- getHomeDirectory
	let curlheader = "X-CSRF-Token: " ++ token
	let cookies = home ++ "/haskerdeux.cookies"
	body <- readProcess "curl" ["-s", "-L", "-c", cookies, "-b", cookies, "-H", curlheader, "https://teuxdeux.com/api/v1/todos/calendar?begin_date="++date++"&end_date="++date] []
	let ok = not ("Invalid CSRF Token" `isInfixOf` body)
	if ok
		then do
			let tds = decodeJSON body :: [Teuxdeux]
			let tdsf = Data.List.filter (\td -> current_date td == date && not (done td)) tds
			return tdsf
		else do
			token <- relogin 
			curlget (token, date)
	

curlpost (token, [date, key, value, apiurl, okresponse]) number = do
	home <- getHomeDirectory
	let cookies = home ++ "/haskerdeux.cookies"
	let curlheader = "X-CSRF-Token: " ++ token
	--Can be much improved, but will do for now:
	json <- if isJust number
		then do
			tdsf <- curlget (token, date)
			let itemid = Main.id $ tdsf!!(read (fromJust number)::Int)
			let modjson = "{ \"ids\" : [\""++show itemid++"\"], \""++key++"\" : \""++value++"\"}"
			return modjson
		else do
			--Can't just straight return these strings, need to let them first
			let newjson = "{ \"current_date\" : \""++date++"\", \""++key++"\" : \""++value++"\"}"
			return newjson
	body <- readProcess "curl" ["-s", "-XPOST", apiurl, "-L", "-c", cookies, "-b", cookies, "-H", curlheader, "-H", "Content-Type: application/json", "-d", json] []
	let ok = not ("Invalid CSRF Token" `isInfixOf` body)
	if ok
		then
			if "done_updated_at" `isInfixOf` body
				then putStrLn okresponse
				else putStrLn "Uh Oh! Didn't work!"
		else do
			token <- relogin 
			curlpost (token, [date, key, value, apiurl, okresponse]) number


curldelete (token, [date, apiurl, okresponse]) number = do
	home <- getHomeDirectory
	let cookies = home ++ "/haskerdeux.cookies"
	tdsf <- curlget (token, date)
	let itemid = Main.id $ tdsf!!(read number::Int)
	let curlheader = "X-CSRF-Token: " ++ token
	body <- readProcess "curl" ["-s", "-XDELETE", apiurl++show itemid, "-c", cookies, "-b", cookies, "-H", curlheader] []
	let ok = not ("Invalid CSRF Token" `isInfixOf` body)
	if ok
		then
			if "done_updated_at" `isInfixOf` body
				then putStrLn okresponse
				else putStrLn "Uh Oh! Didn't work!"
		else do
			token <- relogin 
			curldelete (token, [date, apiurl, okresponse]) number


curlput (token, [date, json, apiurl, okresponse]) number = do
	home <- getHomeDirectory
	let cookies = home ++ "/haskerdeux.cookies"
	tdsf <- curlget (token, date)
	let itemid = Main.id $ tdsf!!(read number::Int)
	let curlheader = "X-CSRF-Token: " ++ token
	body <- readProcess "curl" ["-s", "-XPUT", apiurl++show itemid, "-L", "-c", cookies, "-b", cookies, "-H", curlheader, "-H", "Content-Type: application/json", "-d", json] []
	let ok = not ("Invalid CSRF Token" `isInfixOf` body)
	if ok
		then
			if "done_updated_at" `isInfixOf` body
				then putStrLn okresponse
				else putStrLn "Uh Oh! Didn't work!"
		else do
................................................................................


login  = do
	username <- fmap fst readnetrc
	password <- fmap snd readnetrc
	home <- getHomeDirectory
	savedtoken <- doesFileExist (home ++ "/.haskerdeux-token")
	let cookies = home ++ "/haskerdeux.cookies"
	if savedtoken
		then do
			token <- readFile (home ++ "/.haskerdeux-token")
			return token
		else do
			body <- readProcess "curl" ["-s", "-L", "-c", cookies, "https://teuxdeux.com/login"] []
			token <- getauthtoken body
			writeFile (home ++ "/.haskerdeux-token") token
			let curlheader = "X-CSRF-Token: " ++ token
			let curlpostfields = "username=" ++ username ++ "&password=" ++ password ++ "&authenticity_token=" ++ token
			body <- readProcess "curl" ["-s", "-L", "-c", cookies, "-b", cookies, "-H", curlheader, "-d", curlpostfields, "https://teuxdeux.com/login"] []
			return token


relogin = do
	home <- getHomeDirectory
	removeFile (home ++ "/.haskerdeux-token")
	token <- login
................................................................................
todos (token, [todos_date]) = do
	tdsf <- curlget (token, todos_date)
	putStr $ unlines $ zipWith (\n td -> show n ++ " - " ++ td) [0..] $ Data.List.map text tdsf --numbering from LYAH


new (token, [todos_date, todo]) = do 
	let encodedtodo = Network.URI.Encode.encode todo
	curlpost (token, [todos_date, "text", todo, "https://teuxdeux.com/api/v1/todos", "Added!"]) Nothing


crossoff (token, [todos_date, number]) =
	curlput (token, [todos_date, "{ \"done\": true }", "https://teuxdeux.com/api/v1/todos/", "Crossed Off!"]) number


putoff (token, [todos_date, number]) = do
	let tomorrows_date = show (addDays 1 $ read todos_date::Data.Time.Day)
	curlpost (token, [todos_date, "current_date", tomorrows_date, "https://teuxdeux.com/api/v1/todos/reposition", "Put Off!"]) (Just number)


moveto (token, [todos_date, number, new_date]) =
	--TODO: Need to figure out moving to bottom of a list
	curlpost (token, [todos_date, "current_date", new_date, "https://teuxdeux.com/api/v1/todos/reposition", "Moved!"]) (Just number)