Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 0 additions & 40 deletions designsafe/apps/api/publications/operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
from designsafe.libs.elasticsearch.utils import new_es_client
from django.contrib.auth import get_user_model
from elasticsearch_dsl import Q
import os
import requests
import datetime
import json
import urllib
Expand Down Expand Up @@ -256,41 +254,3 @@ def initilize_publication(publication, status='publishing', revision=None, revis
# Refresh index so that search works in subsequent pipeline operations.
IndexedPublication._index.refresh(using=es_client)
return pub

def clarivate_single_api(doi):

base_url = 'https://api.clarivate.com/apis/wos-starter/v1/documents'
apikey = os.environ.get('WOS_APIKEY')

if not apikey:
return {"error": "Clarivate API key is missing"}

if not doi:
return {"error": "DOI is required"}

params = {'db': 'DRCI', 'q': f"DO={doi}"}

try:
response = requests.get(
base_url,
headers={'X-Apikey': apikey},
params=params
)
response.raise_for_status()
rspdict = response.json()

citations = [
source['count'] for source in rspdict['hits'][0]['citations']
if source['db'] == 'WOK'
][0]

return citations

except requests.exceptions.RequestException as e:
return {
"error": str(e),
}
except (KeyError, IndexError) as e:
return {
"error": "Unexpected response format",
}
5 changes: 3 additions & 2 deletions designsafe/apps/api/publications/urls.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from django.urls import re_path as url
from designsafe.apps.api.publications.views import PublicationListingView, PublicationDetailView, PublicationDataCiteView, PublicationDataCiteEventsView, PublicationClarivateView
from designsafe.apps.api.publications.views import PublicationListingView, PublicationDetailView, PublicationDataCiteView, PublicationDataCiteEventsView
from designsafe.apps.api.publications_v2.views import PublicationClarivateView
from django.http import JsonResponse
from django.views.decorators.cache import cache_page

Expand All @@ -11,7 +12,7 @@
# GET /listing/<file_mgr_name>/<system_id>/<file_path>/
url(r'^data-cite/events$', cache_page(60*15)(PublicationDataCiteEventsView.as_view()), name='publication_datacite_usage'),
url(r'^data-cite/(?P<doi>\S+)$', cache_page(60*15)(PublicationDataCiteView.as_view()), name='publication_datacite'),
url(r'^clarivate/$', cache_page(60*15)(PublicationClarivateView.as_view()), name='publication_clarivate'),
url(r'^clarivate/$', cache_page(60*15)(PublicationClarivateView.as_view()), name='publication_clarivate_legacy'),
url(r'^(?P<operation>[\w.-]+)/$', PublicationListingView.as_view(), name='publication_listing'),
url(r'^(?P<operation>[\w.-]+)/(?P<project_id>[A-Z\-]+-[0-9]+)(v(?P<revision>[0-9]+))?/$', PublicationDetailView.as_view(), name='publication_detail'),
url(r'^(?P<operation>[\w.-]+)/(?P<project_id>[\w.-]+)/$', PublicationDetailView.as_view(), name='legacy-publication_detail'),
Expand Down
18 changes: 0 additions & 18 deletions designsafe/apps/api/publications/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
from django.conf import settings
from requests.exceptions import HTTPError
from designsafe.apps.api.publications import operations
from designsafe.apps.api.publications.operations import clarivate_single_api
from designsafe.apps.projects.managers import datacite as DataciteManager
from django.utils.decorators import method_decorator
import json
Expand Down Expand Up @@ -73,20 +72,3 @@ def get(self, request):
return JsonResponse(events)
except Exception as e:
return JsonResponse({'error': str(e)}, status=500)

"""
API endpoint to retrieve Clarivate citation count for a single DOI.
"""

class PublicationClarivateView(BaseApiView):
def get(self, request):
doi = request.GET.get('doi', '')

if not doi:
return JsonResponse({'error': 'DOI parameter is required'}, status=400)

try:
citations = clarivate_single_api(doi)
return JsonResponse({'doi': doi, 'citation_count': citations})
except Exception as e:
return JsonResponse({'error': str(e)}, status=500)
42 changes: 42 additions & 0 deletions designsafe/apps/api/publications_v2/operations/clarivate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import os
import requests


def clarivate_single_api(doi: str):
"""Fetch Clarivate citation count for a DOI."""
base_url = 'https://api.clarivate.com/apis/wos-starter/v1/documents'
apikey = os.environ.get('WOS_APIKEY')

if not apikey:
return {"error": "Clarivate API key is missing"}

if not doi:
return {"error": "DOI is required"}

params = {'db': 'DRCI', 'q': f"DO={doi}"}

try:
response = requests.get(
base_url,
headers={'X-Apikey': apikey},
params=params
)
response.raise_for_status()
rspdict = response.json()

citations = sum(
source['count']
for source in rspdict['hits'][0]['citations']
if source['db'] in ('WOK', 'PPRN')
)

return citations

except requests.exceptions.RequestException as exc:
return {
"error": str(exc),
}
except (KeyError, IndexError):
return {
"error": "Unexpected response format",
}
3 changes: 3 additions & 0 deletions designsafe/apps/api/publications_v2/urls.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
"""Publication API routes"""

from django.urls import path, re_path
from django.views.decorators.cache import cache_page
from designsafe.apps.api.publications_v2.views import (
PublicationListingView,
PublicationDetailView,
PublicationPublishView,
PublicationAmendView,
PublicationVersionView,
PublicationClarivateView,
)

urlpatterns = [
Expand All @@ -15,6 +17,7 @@
path("publish/", PublicationPublishView.as_view()),
path("amend/", PublicationAmendView.as_view()),
path("version/", PublicationVersionView.as_view()),
path("clarivate/", cache_page(60 * 15)(PublicationClarivateView.as_view())),
re_path(
r"^(?P<project_id>[A-Z\-]+-[0-9]+)(v(?P<version>[0-9]+))?/?$",
PublicationDetailView.as_view(),
Expand Down
17 changes: 17 additions & 0 deletions designsafe/apps/api/publications_v2/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from designsafe.apps.api.views import BaseApiView, ApiException
from designsafe.apps.api.publications_v2.models import Publication
from designsafe.apps.api.publications_v2.elasticsearch import IndexedPublication
from designsafe.apps.api.publications_v2.operations.clarivate import clarivate_single_api
from designsafe.apps.api.projects_v2.operations.project_publish_operations import (
publish_project_async,
amend_publication_async,
Expand Down Expand Up @@ -222,6 +223,22 @@ def get(self, request: HttpRequest):
return JsonResponse({"result": result, "total": total})


class PublicationClarivateView(BaseApiView):
"""API endpoint to retrieve Clarivate citation count for a single DOI."""

def get(self, request: HttpRequest):
doi = request.GET.get("doi", "")

if not doi:
return JsonResponse({"error": "DOI parameter is required"}, status=400)

try:
citations = clarivate_single_api(doi)
return JsonResponse({"doi": doi, "citation_count": citations})
except Exception as exc: # pragma: no cover - passthrough error handling
return JsonResponse({"error": str(exc)}, status=500)


class PublicationDetailView(BaseApiView):
"""View for retrieving publication details."""

Expand Down