File size: 4,164 Bytes
bf73a1e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
574ae04
bf73a1e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
async def download_papers(bib_file, doi_input, dois_input, progress=gr.Progress()):
    if bib_file:
        # Check file type
        if not bib_file.name.lower().endswith('.bib'):
            return None, "Error: Please upload a .bib file", "Error: Please upload a .bib file", None

        zip_path, downloaded_dois, failed_dois, _ = await downloader.process_bibtex_async(bib_file, progress)
        return zip_path, downloaded_dois, failed_dois, None
    elif doi_input:
        filepath, message, failed_doi = downloader.download_single_doi(doi_input, progress)
        return None, message, failed_doi, filepath
    elif dois_input:
        zip_path, downloaded_dois, failed_dois = downloader.download_multiple_dois(dois_input, progress)
        return zip_path, downloaded_dois, failed_dois, None
    else:
        return None, "Please provide a .bib file, a single DOI, or a list of DOIs", "Please provide a .bib file, a single DOI, or a list of DOIs", None

# Gradio Interface
interface = gr.Interface(
    fn=download_papers,
    inputs=[
        gr.File(file_types=['.bib'], label="Upload BibTeX File"),
        gr.Textbox(label="Enter Single DOI", placeholder="10.xxxx/xxxx"),
        gr.Textbox(label="Enter Multiple DOIs (one per line)", placeholder="10.xxxx/xxxx\n10.yyyy/yyyy\n...")
    ],
    outputs=[
        gr.File(label="Download Papers (ZIP) or Single PDF"),
        gr.HTML(label="""
            <div style='padding-bottom: 5px; font-weight: bold;'>
                Found DOIs
            </div>
            <div style='border: 1px solid #ddd; padding: 5px; border-radius: 5px;'>
                <div id="downloaded-dois"></div>
            </div>
        """),
        gr.HTML(label="""
            <div style='padding-bottom: 5px; font-weight: bold;'>
                Missed DOIs
            </div>
            <div style='border: 1px solid #ddd; padding: 5px; border-radius: 5px;'>
                <div id="failed-dois"></div>
            </div>
        """),
        gr.File(label="Downloaded Single PDF")
    ],
    title="🔬 Academic Paper Batch Downloader",
    description="Upload a BibTeX file or enter DOIs to download PDFs. We'll attempt to fetch PDFs from multiple sources like Sci-Hub, Libgen, Google Scholar and Crossref. You can use any of the three inputs at any moment.",
    theme="Hev832/Applio",
    examples=[
        ["example.bib", None, None],  # Bibtex File
        [None, "10.1038/nature12373", None],  # Single DOI
        [None, None, "10.1109/5.771073\n10.3390/horticulturae8080677"],  # Multiple DOIs
    ],
    css="""
    .gradio-container {
        background-color: black;
    }
    .gr-interface {
        max-width: 800px;
        margin: 0 auto;
    }
    .gr-box {
        background-color: black;
        border-radius: 10px;
        box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
    }
       .output-text a {
           color: #007bff; /* Blue color for hyperlinks */
        }
    """,
    cache_examples=False,
)

# Add Javascript to update HTML
interface.load = """
   function(downloaded_dois, failed_dois) {
      let downloaded_html = '';
      downloaded_dois.split('\\n').filter(Boolean).forEach(doi => {
          downloaded_html +=  doi + '<br>';
      });
      document.querySelector("#downloaded-dois").innerHTML = downloaded_html;

      let failed_html = '';
        failed_dois.split('\\n').filter(Boolean).forEach(doi => {
        failed_html += doi + '<br>';
      });
      document.querySelector("#failed-dois").innerHTML = failed_html;
      return [downloaded_html, failed_html];
   }
"""

interface.head = """
<script>
    function copyLink(button) {
        const linkElement = button.previousElementSibling;
        const link = linkElement.href;
        navigator.clipboard.writeText(link)
        .then(() => {
            button.innerText = '✓ Copied';
            button.style.color = 'green';
            setTimeout(() => {
                button.innerText = 'Copy';
                button.style.color = '';
            }, 2000);
        })
        .catch(err => {
            console.error('Failed to copy link: ', err);
        });
    }
</script>
"""
return interface