Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
O
openalex
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
3
Issues
3
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
gargantext
crawlers
openalex
Commits
d7283561
Verified
Commit
d7283561
authored
Jun 28, 2023
by
Przemyslaw Kaminski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
More conduit/cmdline fixes. Added filter to client query
parent
8d3a0ab8
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
59 additions
and
40 deletions
+59
-40
Main.hs
app/Main.hs
+19
-18
OpenAlex.hs
src/OpenAlex.hs
+26
-16
Client.hs
src/OpenAlex/Client.hs
+5
-3
Types.hs
src/OpenAlex/Types.hs
+9
-3
No files found.
app/Main.hs
View file @
d7283561
...
...
@@ -9,6 +9,7 @@ import qualified OpenAlex.Types as OA
main
::
IO
()
main
=
do
let
filterHelp
=
help
"Filter, for example: display_name.search:einstein , see https://docs.openalex.org/how-to-use-the-api/get-lists-of-entities/filter-entity-lists"
(
opts
,
runCmd
)
<-
simpleOptions
"0.1.0.0"
"OpenAlex"
...
...
@@ -16,46 +17,46 @@ main = do
(
pure
()
)
$
do
addCommand
"concepts"
"Fetch OpenAlex concepts (https://docs.openalex.org/api-entities/concepts/concept-object)"
(
const
fetchConcepts
)
(
pure
(
)
)
fetchConcepts
(
strOption
(
long
"filter"
))
addCommand
"works"
"Fetch OpenAlex works (https://docs.openalex.org/api-entities/works/work-object)"
(
const
fetchWorks
)
(
pure
(
)
)
fetchWorks
(
strOption
(
long
"filter"
))
addCommand
"works-c"
"Fetch OpenAlex works (https://docs.openalex.org/api-entities/works/work-object) with conduit"
(
const
fetchWorksC
)
(
pure
(
)
)
fetchWorksC
(
strOption
(
long
"filter"
))
runCmd
()
fetchConcepts
::
()
->
IO
()
fetchConcepts
_
=
do
ec
<-
OA
.
fetchConcepts
(
Just
1
)
(
Just
1
)
(
Just
"*"
)
fetchConcepts
::
OA
.
Filter
->
()
->
IO
()
fetchConcepts
fltr
_
=
do
ec
<-
OA
.
fetchConcepts
(
Just
1
)
(
Just
1
)
(
Just
"*"
)
(
Just
fltr
)
case
ec
of
Left
err
->
putText
$
"error: "
<>
show
err
Right
c
->
do
putText
$
show
c
fetchWorks
::
()
->
IO
()
fetchWorks
_
=
do
ew
<-
OA
.
fetchWorks
(
Just
1
)
(
Just
1
)
(
Just
"*"
)
fetchWorks
::
OA
.
Filter
->
()
->
IO
()
fetchWorks
fltr
_
=
do
ew
<-
OA
.
fetchWorks
(
Just
1
)
(
Just
1
)
(
Just
"*"
)
(
Just
fltr
)
case
ew
of
Left
err
->
putText
$
"error: "
<>
show
err
Right
w
->
do
putText
$
show
w
fetchWorksC
::
()
->
IO
()
fetchWorksC
_
=
do
eWorksC
<-
OA
.
fetchWorksC
Nothing
fetchWorksC
::
OA
.
Filter
->
()
->
IO
()
fetchWorksC
fltr
_
=
do
eWorksC
<-
OA
.
fetchWorksC
Nothing
(
Just
fltr
)
case
eWorksC
of
Left
err
->
putText
$
"error: "
<>
show
err
Right
(
Just
c
ount
,
c
)
->
do
putText
$
"Count: "
<>
show
c
ount
Right
(
mC
ount
,
c
)
->
do
putText
$
"Count: "
<>
show
mC
ount
_
<-
runConduit
$
c
.|
takeC
1000
.|
mapM_C
(
\
(
OA
.
Work
{
..
})
->
do
liftIO
$
putText
$
show
id
liftIO
$
putText
$
show
id
<>
" :: "
<>
show
display_name
)
pure
()
src/OpenAlex.hs
View file @
d7283561
...
...
@@ -27,7 +27,7 @@ import Network.HTTP.Client.TLS (tlsManagerSettings)
import
Protolude
hiding
(
yield
)
import
OpenAlex.Client
import
OpenAlex.ServantClientLogging
import
OpenAlex.Types
(
ListOf
(
..
),
Meta
(
..
),
Page
,
PerPage
,
Cursor
,
Concept
,
Work
)
import
OpenAlex.Types
(
ListOf
(
..
),
Meta
(
..
),
Page
,
PerPage
,
Cursor
,
Filter
,
Concept
,
Work
)
import
Servant.Client
(
BaseUrl
(
..
),
ClientEnv
(
..
),
ClientError
,
Scheme
(
Https
),
defaultMakeClientRequest
,
mkClientEnv
,
runClientM
)
defaultClientEnv
::
IO
ClientEnv
...
...
@@ -41,23 +41,33 @@ defaultClientEnv = do
pure
$
addLoggingToClientEnv
env
fetchConcepts
::
Maybe
Page
->
Maybe
PerPage
->
Maybe
Cursor
->
IO
(
Either
ClientError
(
ListOf
Concept
))
fetchConcepts
mPage
mPerPage
mCursor
=
do
fetchConcepts
::
Maybe
Page
->
Maybe
PerPage
->
Maybe
Cursor
->
Maybe
Filter
->
IO
(
Either
ClientError
(
ListOf
Concept
))
fetchConcepts
mPage
mPerPage
mCursor
mFilter
=
do
env
<-
defaultClientEnv
runClientM
(
concepts
mPage
mPerPage
mCursor
)
env
runClientM
(
concepts
mPage
mPerPage
mCursor
mFilter
)
env
fetchWorks
::
Maybe
Page
->
Maybe
PerPage
->
Maybe
Cursor
->
IO
(
Either
ClientError
(
ListOf
Work
))
fetchWorks
mPage
mPerPage
mCursor
=
do
fetchWorks
::
Maybe
Page
->
Maybe
PerPage
->
Maybe
Cursor
->
Maybe
Filter
->
IO
(
Either
ClientError
(
ListOf
Work
))
fetchWorks
mPage
mPerPage
mCursor
mFilter
=
do
env
<-
defaultClientEnv
runClientM
(
works
mPage
mPerPage
mCursor
)
env
runClientM
(
works
mPage
mPerPage
mCursor
mFilter
)
env
fetchWorksC
::
Maybe
Cursor
->
IO
(
Either
ClientError
(
Maybe
Integer
,
ConduitT
()
Work
IO
()
))
fetchWorksC
Nothing
=
do
fetchWorksC
(
Just
"*"
)
fetchWorksC
mCursor
=
do
fetchWorksC
::
Maybe
Cursor
->
Maybe
Filter
->
IO
(
Either
ClientError
(
Maybe
Integer
,
ConduitT
()
Work
IO
()
))
fetchWorksC
Nothing
mFilter
=
do
fetchWorksC
(
Just
"*"
)
mFilter
fetchWorksC
mCursor
mFilter
=
do
env
<-
defaultClientEnv
-- NOTE: per-page max is 200
eRes
<-
runClientM
(
works
(
Just
1
)
(
Just
1
)
Nothing
)
env
eRes
<-
runClientM
(
works
(
Just
1
)
(
Just
1
)
Nothing
mFilter
)
env
case
eRes
of
Left
err
->
pure
$
Left
err
Right
ListOf
{
meta
=
Meta
{
count
}}
->
do
...
...
@@ -66,11 +76,11 @@ fetchWorksC mCursor = do
where
producer
::
ClientEnv
->
Maybe
Cursor
->
ConduitT
()
Work
IO
()
producer
env
mCursor'
=
do
eRes
<-
liftIO
$
runClientM
(
works
Nothing
(
Just
20
)
mCursor'
)
env
liftIO
$
putText
$
"Conduit fetching page with cursor "
<>
show
mCursor'
eRes
<-
liftIO
$
runClientM
(
works
Nothing
(
Just
20
0
)
mCursor'
mFilter
)
env
--
liftIO $ putText $ "Conduit fetching page with cursor " <> show mCursor'
case
eRes
of
Left
err
->
panic
$
"error: "
<>
show
err
Right
(
ListOf
{
results
,
meta
=
meta
@
(
Meta
{
next_cursor
})
})
->
do
liftIO
$
putText
$
"Meta: "
<>
show
meta
Right
(
ListOf
{
results
,
meta
=
_
meta
@
(
Meta
{
next_cursor
})
})
->
do
--
liftIO $ putText $ "Meta: " <> show meta
yieldMany
results
producer
env
next_cursor
src/OpenAlex/Client.hs
View file @
d7283561
...
...
@@ -16,7 +16,7 @@ import Protolude
import
Servant.API
import
Servant.Client
import
OpenAlex.Types
(
Page
,
PerPage
,
Cursor
,
ListOf
(
..
),
Concept
,
Work
)
import
OpenAlex.Types
(
Page
,
PerPage
,
Cursor
,
Filter
,
ListOf
(
..
),
Concept
,
Work
)
type
API_URL
=
Text
apiUrl
::
API_URL
...
...
@@ -34,6 +34,7 @@ type OpenAlexAPI =
:>
QueryParam
"page"
Page
:>
QueryParam
"per-page"
PerPage
:>
QueryParam
"cursor"
Cursor
:>
QueryParam
"filter"
Filter
-- TODO: filter, search, sort
:>
Get
'[
J
SON
]
(
ListOf
Concept
)
...
...
@@ -42,14 +43,15 @@ type OpenAlexAPI =
:>
QueryParam
"page"
Page
:>
QueryParam
"per-page"
PerPage
:>
QueryParam
"cursor"
Cursor
:>
QueryParam
"filter"
Filter
-- TODO: filter, search, sort
:>
Get
'[
J
SON
]
(
ListOf
Work
)
openAlexApi
::
Proxy
OpenAlexAPI
openAlexApi
=
Proxy
concepts
::
Maybe
Page
->
Maybe
PerPage
->
Maybe
Cursor
->
ClientM
(
ListOf
Concept
)
concepts
::
Maybe
Page
->
Maybe
PerPage
->
Maybe
Cursor
->
Maybe
Filter
->
ClientM
(
ListOf
Concept
)
works
::
Maybe
Page
->
Maybe
PerPage
->
Maybe
Cursor
->
ClientM
(
ListOf
Work
)
works
::
Maybe
Page
->
Maybe
PerPage
->
Maybe
Cursor
->
Maybe
Filter
->
ClientM
(
ListOf
Work
)
concepts
:<|>
works
=
client
openAlexApi
src/OpenAlex/Types.hs
View file @
d7283561
...
...
@@ -23,9 +23,17 @@ import Data.Time.Calendar (Day)
import
qualified
Data.Time.Format
as
DTF
import
Protolude
hiding
(
Location
,
Meta
)
-- API request types
type
Cursor
=
Text
type
Page
=
Int
type
PerPage
=
Int
type
Filter
=
Text
-- API response types
type
Count
=
Int
type
Cursor
=
Text
type
DOI
=
Text
data
ExternalID
=
ExtIDUrl
URL
|
ExtIDUrls
[
URL
]
|
ExtIDInt
Int
deriving
(
Generic
,
Show
)
...
...
@@ -54,8 +62,6 @@ instance FromJSON OAStatus where
parseJSON
(
String
"closed"
)
=
pure
OAClosed
parseJSON
_
=
fail
"Don't know how to parse this oa status"
type
OpenAlexID
=
Text
type
Page
=
Int
type
PerPage
=
Int
type
URL
=
Text
type
Year
=
Int
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment