2025-10-14: Manual update, main structure done

This commit is contained in:
Moussouni, Yaël
2025-10-14 10:21:09 +02:00
parent 7baa9137bf
commit 6171b6aa15
12 changed files with 523 additions and 39 deletions

101
.gitignore vendored
View File

@@ -1,10 +1,97 @@
.DS_Store # Specific files
*.tmp
*.log
tmp/
log/
venv/
.venv/
cfg/filters cfg/filters
*.secret *.secret
db/ db/
# Os generated files
## Linux
.Trash-*
## MacOS
.DS_Store
.AppleDouble
.LSOverride
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
._*
## Windows
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db
Desktop.ini
desktop.ini
$RECYCLE.BIN/
# temporary or log(s) files and directories
*.tmp
*.log
*.logs
tmp/
log/
logs/
# Python
venv/
.venv/
__pycache__/
# LaTeX
Build/
build/
*.acn
*.acr
*.alg
*.aux
*.bak
*.bbl
*.bcf
*.blg
*.brf
*.bst
*.dvi
*.fdb_latexmk
*.fls
*.glg
*.glo
*.gls
*.idx
*.ilg
*.ind
*.ist
*.lof
*.log
*.lol
*.lot
*.maf
*.mtc
*.mtc1
*.nav
*.nlo
*.nls
*.out
*.pyg
*.run.xml
*.snm
*.synctex.gz
*.tex.backup
*.tex~
*.thm
*.toc
*.vrb
*.xdy
*.xml
*blx.bib
.bak
.mtc

View File

@@ -32,7 +32,7 @@ mkdir -p -v cfg/filters
mkdir -p -v db mkdir -p -v db
touch db/read.bib touch db/read.bib
touch db/unread.bib touch db/unread.bib
touch db/library.bib touch db/local.bib
chmod u+x *.sh chmod u+x *.sh
echo "=== Done ===" echo "=== Done ==="

View File

@@ -93,8 +93,8 @@ def ads_bibcode(bibcodes):
bibentry = feed.text bibentry = feed.text
bibentry = bibentry[:-2] bibentry = bibentry[:-2]
bibentry += (",\n" bibentry += (",\n"
"\tarxtic_notes={},\n" "\tarxtic_comment={},\n"
"\tarxtic_category={},\n" "\tarxtic_library={},\n"
"\tarxtic_keywords={},\n" "\tarxtic_keywords={},\n"
"\tarxtic_score={-1},\n" "\tarxtic_score={-1},\n"
"\tarxtic_filename={},\n" "\tarxtic_filename={},\n"

View File

@@ -102,8 +102,8 @@ def parse_bibtex(entries,
f"\teprint={{{eprint}}},\n" f"\teprint={{{eprint}}},\n"
f"\turl={{{url}}},\n" f"\turl={{{url}}},\n"
f"\tabstract={{{abstract}}},\n" f"\tabstract={{{abstract}}},\n"
"\tarxtic_notes={},\n" "\tarxtic_comment={},\n"
"\tarxtic_category={},\n" "\tarxtic_library={},\n"
"\tarxtic_keywords={},\n" "\tarxtic_keywords={},\n"
"\tarxtic_score={-1},\n" "\tarxtic_score={-1},\n"
"\tarxtic_filename={},\n" "\tarxtic_filename={},\n"

View File

@@ -31,6 +31,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see www.gnu.org/licenses/. along with this program. If not, see www.gnu.org/licenses/.
""" """
import os import os
import subprocess
from urllib.parse import urlencode, quote_plus from urllib.parse import urlencode, quote_plus
import requests as rq import requests as rq
@@ -59,9 +60,138 @@ ids = ["2510.06329", "2509.13163"]
bibcodes = ["2022A&A...658A.152V", "2021A&A...649A..97L"] bibcodes = ["2022A&A...658A.152V", "2021A&A...649A..97L"]
query = "first_author:\"Voggel, K\"year:(2022)" query = "first_author:\"Voggel, K\"year:(2022)"
utils.print_reference(arxiv_api.arxiv_today()) #test1 = local_api.update_local_pdf()
utils.print_title_author(arxiv_api.arxiv_id(ids)) #local_api.bibtex_to_file(test1, "test1")
print(ads_api.ads_bibcode_search(query, num=2)) #test1 = local_api.file_to_bibtex("test1")
utils.print_abstract(ads_api.ads_bibcode(bibcodes)) #test2 = bib.Library()
#
#utils.arxtic_comment("2022ApJ...941L..11F", test1)
#utils.arxtic_library_add("2022ApJ...941L..11F", test1, "test1")
#utils.arxtic_keywords_add("2022ApJ...941L..11F", test1, "kw1")
#utils.arxtic_score("2022ApJ...941L..11F", test1, "42")
#utils.arxtic_date_read("2022ApJ...941L..11F", test1)
#utils.export_abstract(test1, "test1")
if __name__ == "__main__":
q = False
s = True
libraries_names = [f.replace(".bib", "") for f in os.listdir(DB_DIR)
if not f[0] == "." and ".bib" in f]
libraries = {l: local_api.file_to_bibtex(l + ".bib")
for l in libraries_names}
while not q:
print(COLOUR_INPUT + "Select an action")
val = input("> " + COLOUR_DEFAULT)
args = val.split(" ")
nargs = len(args)
arg0 = args[0].lower()
try:
if arg0 in ["quit", "exit", "q"]:
if s == True:
q = True
else:
raise Exception(("Unsaved changes, "
"type \"save\" to update database or "
"type \"cancel\" to discard"))
elif arg0 in ["save", "write"]:
for i in range(len(libraries)):
lib_name = libraries_names[i]
lib = libraries[lib_name]
local_api.bibtex_to_file(lib, lib_name)
s = True
elif arg0 in ["cancel", "reset", "reload"]:
for i in range(len(libraries)):
lib_name = libraries_names[i]
libraries[lib_name] = local_api.file_to_bibtex(lib_name)
s = True
elif arg0 in ["local"]:
libraries["local"] = local_api.update_local_pdf(
library=libraries["local"])
elif arg0 in ["print"]:
if nargs == 2:
utils.print_abstract(libraries[args[1]])
elif nargs == 3:
if args[2] in ["abstract", "abs"]:
utils.print_abstract(libraries[args[1]])
if args[2] in ["title", "author", "authors"]:
utils.print_title_author(libraries[args[1]])
if args[2] in ["reference", "references", "ref", "refs"]:
utils.print_reference(libraries[args[1]])
else:
raise Exception("Not recognized")
elif arg0 in ["export"]:
if nargs == 1:
for i in range(len(libraries)):
lib_name = libraries_names[i]
lib = libraries[lib_name]
utils.export_abstract(lib, lib_name+".txt")
elif nargs == 2:
utils.export_abstract(libraries[args[1]], args[1]+".txt")
elif nargs == 3:
if args[2] in ["abstract", "abs"]:
utils.export_abstract(libraries[args[1]], args[1]+".txt")
if args[2] in ["title", "author", "authors"]:
utils.export_title_author(libraries[args[1]], args[1]+".txt")
if args[2] in ["reference", "references", "ref", "refs"]:
utils.export_reference(libraries[args[1]], args[1]+".txt")
else:
raise Exception("Not recognized")
elif arg0 in ["mv", "move"]:
if nargs == 4:
utils.mv(args[1], libraries[args[2]], libraries[args[3]])
s = False
else:
raise Exception("Not recognized")
elif arg0 in ["cp", "copy"]:
if nargs == 4:
utils.cp(args[1], libraries[args[2]], libraries[args[3]])
s = False
else:
raise Exception("Not recognized")
elif arg0 in ["rm", "remove", "del", "delete"]:
if nargs == 3:
utils.rm(args[1], libraries[args[2]])
s = False
else:
raise Exception("Not recognized")
elif arg0 in ["comment"]:
if nargs == 3:
utils.arxtic_comment(args[2], libraries[args[2]])
s = False
elif arg0 in ["read"]:
if nargs == 2:
utils.launch_reader(args[1], libraries["local"])
utils.arxtic_comment(args[1], libraries["local"])
s = False
elif nargs == 3:
utils.launch_reader(args[1], libraries[args[2]])
utils.arxtic_comment(args[1], libraries[args[2]])
s = False
else:
raise Exception("Not recognized")
else:
raise Exception("Not recognized")
except Exception as err:
msg = str(err)
print(COLOUR_ERROR + "Error! " + msg + COLOUR_DEFAULT)
utils.print_reference(local_api.update_local_pdf())

View File

@@ -76,7 +76,7 @@ def update_local_pdf(library=None, directory=PDF_DIR):
known_pdf = [block["arxtic_filename"] for block in blocks] known_pdf = [block["arxtic_filename"] for block in blocks]
folder_pdf = [f for f in os.listdir(directory) folder_pdf = [f for f in os.listdir(directory)
if not f[0] == "." and ".pdf" if f] if not f[0] == "." and ".pdf" in f]
for pdf in folder_pdf: for pdf in folder_pdf:
fields = pdf.replace(".pdf", "").split("_") fields = pdf.replace(".pdf", "").split("_")
@@ -92,6 +92,7 @@ def update_local_pdf(library=None, directory=PDF_DIR):
arxiv_id = "/".join(fields[2:]) arxiv_id = "/".join(fields[2:])
arxiv_library = arxiv_api.arxiv_id(arxiv_id) arxiv_library = arxiv_api.arxiv_id(arxiv_id)
if len(arxiv_library.blocks) == 1: if len(arxiv_library.blocks) == 1:
arxiv_library.blocks[0]["arxtic_filename"] = pdf
library.add(arxiv_library.blocks) library.add(arxiv_library.blocks)
else: else:
print(COLOUR_WARNING print(COLOUR_WARNING
@@ -113,6 +114,7 @@ def update_local_pdf(library=None, directory=PDF_DIR):
bibcodes = ads_api.ads_bibcode_search(query, num=2) bibcodes = ads_api.ads_bibcode_search(query, num=2)
if len(bibcodes) == 1: if len(bibcodes) == 1:
ads_library = ads_api.ads_bibcode(bibcodes) ads_library = ads_api.ads_bibcode(bibcodes)
ads_library.blocks[0]["arxtic_filename"] = pdf
library.add(ads_library.blocks) library.add(ads_library.blocks)
else: else:
print(COLOUR_WARNING print(COLOUR_WARNING

View File

@@ -31,6 +31,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see www.gnu.org/licenses/. along with this program. If not, see www.gnu.org/licenses/.
""" """
import os import os
import subprocess
from urllib.parse import urlencode, quote_plus from urllib.parse import urlencode, quote_plus
import requests as rq import requests as rq
@@ -38,6 +39,7 @@ import numpy as np
import textwrap as tw import textwrap as tw
import feedparser as fp import feedparser as fp
import bibtexparser as bib import bibtexparser as bib
import datetime as dt
FILTERS_DIR = os.environ.get("FILTERS_DIR") FILTERS_DIR = os.environ.get("FILTERS_DIR")
DB_DIR = os.environ.get("DB_DIR") DB_DIR = os.environ.get("DB_DIR")
@@ -50,27 +52,76 @@ COLOUR_INFO="\033[34m"
COLOUR_WARNING = "\033[93m" COLOUR_WARNING = "\033[93m"
COLOUR_ERROR = "\033[91m" COLOUR_ERROR = "\033[91m"
COLOUR_REF = "\033[34m"
COLOUR_TITLE = "\033[35m"
COLOUR_AUTHOR = "\033[32m"
COLOUR_ABS = "\033[36m"
COLOUR_ARXTIC = "\033[91m"
## General
def wrap(txt, length=80): def wrap(txt, length=80):
wrapped_txt = '\n'.join(tw.wrap(txt, length, break_long_words=False)) wrapped_txt = '\n'.join(tw.wrap(txt, length, break_long_words=False))
return wrapped_txt return wrapped_txt
## Prints
def print_abstract(library): def print_abstract(library):
if not isinstance(library, bib.Library): if not isinstance(library, bib.Library):
library = bib.Library(library) library = bib.Library(library)
for block in library.blocks: for block in library.blocks:
if isinstance(block, bib.model.Block): if isinstance(block, bib.model.Block):
print(COLOUR_INFO, end="") print("#"
print(block.key, end="") + COLOUR_REF
print(" [" + block["url"] + "]", end="") + block.key + " [" + block["url"] + "]"
print(COLOUR_DEFAULT) + COLOUR_DEFAULT)
if block["arxtic_filename"] != "":
print(COLOUR_DEFAULT + wrap(block["title"]) + COLOUR_DEFAULT) print(COLOUR_REF
print(COLOUR_OUTPUT + "("
+ PDF_DIR
+ block["arxtic_filename"]
+ ")"
+ COLOUR_DEFAULT)
print("Title: "
+ COLOUR_TITLE
+ wrap(block["title"])
+ COLOUR_DEFAULT)
print("Author(s): "
+ COLOUR_AUTHOR
+ wrap(", ".join(block["author"].split(" and "))) + wrap(", ".join(block["author"].split(" and ")))
+ COLOUR_DEFAULT) + COLOUR_DEFAULT)
print(COLOUR_INPUT print("Abstract: "
+ COLOUR_ABS
+ wrap(block["abstract"]) + wrap(block["abstract"])
+ COLOUR_DEFAULT) + COLOUR_DEFAULT)
if block["arxtic_comment"] != "":
print("Comment: "
+ COLOUR_ARXTIC
+ wrap(block["arxtic_comment"])
+ COLOUR_DEFAULT)
if block["arxtic_library"] != "":
print("Library: "
+ COLOUR_ARXTIC
+ ", ".join(block["arxtic_library"].split(","))
+ COLOUR_DEFAULT)
if block["arxtic_keywords"] != "":
print("Keywords: "
+ COLOUR_ARXTIC
+ ", ".join(block["arxtic_library"].split(","))
+ COLOUR_DEFAULT)
if float(block["arxtic_score"]) >= 0:
print("Score: "
+ COLOUR_ARXTIC
+ block["arxtic_score"]
+ COLOUR_DEFAULT)
if block["arxtic_date_read"] != "":
print("Read date: "
+ COLOUR_ARXTIC
+ block["arxtic_date_read"]
+ COLOUR_DEFAULT)
print("")
print(80*"=")
print("") print("")
return 0 return 0
@@ -79,15 +130,52 @@ def print_title_author(library):
library = bib.Library(library) library = bib.Library(library)
for block in library.blocks: for block in library.blocks:
if isinstance(block, bib.model.Block): if isinstance(block, bib.model.Block):
print(COLOUR_INFO, end="") print("#"
print(block.key, end="") + COLOUR_REF
print(" [" + block["url"] + "]", end="") + block.key + " [" + block["url"] + "]"
print(COLOUR_DEFAULT) + COLOUR_DEFAULT)
if block["arxtic_filename"] != "":
print(COLOUR_DEFAULT + wrap(block["title"]) + COLOUR_DEFAULT) print(COLOUR_REF
print(COLOUR_OUTPUT + "("
+ PDF_DIR
+ block["arxtic_filename"]
+ ")"
+ COLOUR_DEFAULT)
print("Title: "
+ COLOUR_TITLE
+ wrap(block["title"])
+ COLOUR_DEFAULT)
print("Author(s): "
+ COLOUR_AUTHOR
+ wrap(", ".join(block["author"].split(" and "))) + wrap(", ".join(block["author"].split(" and ")))
+ COLOUR_DEFAULT) + COLOUR_DEFAULT)
if block["arxtic_comment"] != "":
print("Comment: "
+ COLOUR_ARXTIC
+ wrap(block["arxtic_comment"])
+ COLOUR_DEFAULT)
if block["arxtic_library"] != "":
print("Library: "
+ COLOUR_ARXTIC
+ ", ".join(block["arxtic_library"].split(","))
+ COLOUR_DEFAULT)
if block["arxtic_keywords"] != "":
print("Keywords: "
+ COLOUR_ARXTIC
+ ", ".join(block["arxtic_library"].split(","))
+ COLOUR_DEFAULT)
if float(block["arxtic_score"]) >= 0:
print("Score: "
+ COLOUR_ARXTIC
+ block["arxtic_score"]
+ COLOUR_DEFAULT)
if block["arxtic_date_read"] != "":
print("Read date: "
+ COLOUR_ARXTIC
+ block["arxtic_date_read"]
+ COLOUR_DEFAULT)
print("")
print(80*"=")
print("") print("")
return 0 return 0
@@ -101,3 +189,180 @@ def print_reference(library):
print(" [" + block["url"] + "]", end="") print(" [" + block["url"] + "]", end="")
print(COLOUR_DEFAULT) print(COLOUR_DEFAULT)
return 0 return 0
## Exports
def export_abstract(library, filename, directory=PDF_DIR):
if not isinstance(library, bib.Library):
library = bib.Library(library)
with open(directory + filename, "w+") as file:
for block in library.blocks:
if isinstance(block, bib.model.Block):
file.write("#" + block.key + " [" + block["url"] + "]\n")
file.write(wrap("Title: " + block["title"]) + "\n")
file.write(wrap("Author(s): "
+ ", ".join(block["author"].split(" and ")))
+ "\n")
file.write(wrap("Abstract: " + block["abstract"]) + "\n")
if block["arxtic_comment"] != "":
file.write(wrap("Comment: " + block["arxtic_comment"])
+ "\n")
if block["arxtic_library"] != "":
file.write("Library: "
+ ", ".join(block["arxtic_library"].split(","))
+ "\n")
if block["arxtic_keywords"] != "":
file.write("Keywords: "
+ ", ".join(block["arxtic_library"].split(","))
+ "\n")
if float(block["arxtic_score"]) >= 0:
file.write("Score: " + block["arxtic_score"] + "\n")
if block["arxtic_date_read"] != "":
file.write("Read date: " + block["arxtic_date_read"] + "\n")
file.write("\n" + 80*"=" + "\n")
file.write("\n")
return 0
def export_title_author(library, filename, directory=PDF_DIR):
if not isinstance(library, bib.Library):
library = bib.Library(library)
with open(directory + filename, "w+") as file:
for block in library.blocks:
if isinstance(block, bib.model.Block):
file.write("#" + block.key + " [" + block["url"] + "]\n")
file.write(wrap("Title: " + block["title"]) + "\n")
file.write(wrap("Author(s): "
+ ", ".join(block["author"].split(" and ")))
+ "\n")
if block["arxtic_comment"] != "":
file.write(wrap("Comment: " + block["arxtic_comment"])
+ "\n")
if block["arxtic_library"] != "":
file.write("Library: "
+ ", ".join(block["arxtic_library"].split(","))
+ "\n")
if block["arxtic_keywords"] != "":
file.write("Keywords: "
+ ", ".join(block["arxtic_library"].split(","))
+ "\n")
if float(block["arxtic_score"]) >= 0:
file.write("Score: " + block["arxtic_score"] + "\n")
if block["arxtic_date_read"] != "":
file.write("Read date: " + block["arxtic_date_read"] + "\n")
file.write("\n" + 80*"=" + "\n")
file.write("\n")
return 0
def export_reference(library, filename, directory=PDF_DIR):
if not isinstance(library, bib.Library):
library = bib.Library(library)
with open(directory + filename, "w+") as file:
for block in library.blocks:
if isinstance(block, bib.model.Block):
file.write("#" + block.key + " [" + block["url"] + "]\n")
return 0
## Manipulation
def find(key, library):
blocks = library.blocks
i = 0
while i < len(blocks):
block = blocks[i]
if isinstance(block, bib.model.Block):
if block.key == key:
return block
i += 1
return None
def mv(key, lib_from, lib_to):
block = find(key, lib_from)
lib_to.add(block)
lib_from.remove(block)
return lib_from, lib_to
def cp(key, lib_from, lib_to):
block = find(key, lib_from)
lib_to.add(block)
return lib_from, lib_to
def rm(key, library):
block = find(key, library)
library.remove(block)
return library
## ArXtic parameters
def arxtic_comment(key, library):
block = find(key, library)
comment = block["arxtic_comment"]
with open("comment.tmp", "w+") as file:
file.write(comment)
subprocess.run(["nvim", "comment.tmp"])
with open("comment.tmp", "r") as file:
comment = "".join(file.readlines())
subprocess.run(["rm", "comment.tmp"])
block["arxtic_comment"] = comment
return library
def arxtic_library_add(key, library, value):
block = find(key, library)
old_value = block["arxtic_library"]
new_value = old_value + "," + value
if new_value[0] == ",": new_value = new_value[1:]
if new_value[-1] == ",": new_value = new_value[:-1]
block["arxtic_library"] = new_value
return library
def arxtic_library_remove(key, library, value):
block = find(key, library)
old_value = block["arxtic_library"]
new_value = old_value.replace(value, "").replace(",,", ",")
if new_value[0] == ",": new_value = new_value[1:]
if new_value[-1] == ",": new_value = new_value[:-1]
block["arxtic_library"] = new_value
return library
def arxtic_keywords_add(key, library, value):
block = find(key, library)
old_value = block["arxtic_keywords"]
new_value = old_value + "," + value
if new_value[0] == ",": new_value = new_value[1:]
if new_value[-1] == ",": new_value = new_value[:-1]
block["arxtic_keywords"] = new_value
return library
def arxtic_keywords_remove(key, library, value):
block = find(key, library)
old_value = block["arxtic_keywords"]
new_value = old_value.replace(value, "").replace(",,", ",")
if new_value[0] == ",": new_value = new_value[1:]
if new_value[-1] == ",": new_value = new_value[:-1]
block["arxtic_keywords"] = new_value
return library
def arxtic_score(key, library, score):
block = find(key, library)
block["arxtic_score"] = score
return library
def arxtic_date_read(key, library, date=None):
block = find(key, library)
if date is None:
date = dt.datetime.now()
block["arxtic_date_read"] = date.strftime("%Y-%m-%d")
return library
def arxtic_filename(key, library, filename):
block = find(key, library)
block["arxtic_filename"] = filename
return library
## External reader
def launch_reader(key, library, directory=PDF_DIR):
block = find(key, library)
fname = block["arxtic_filename"]
subprocess.Popen(["/bin/flatpak", "run", "com.github.ahrm.sioyek", directory+fname],
stdout = subprocess.DEVNULL,
stderr = subprocess.DEVNULL)