% Package users acknowledge the following: I understand that this package provides a probabilistic match between names found in my .bib file and publicly available lists of individuals accused of, or convicted of sexual harassment and/or other academic misconduct. It is my responsibility to verify the information provided in these databases, to ensure that the match is accurate, and I am entirely responsible for any action I take as a result of learning of the match. I acknowledge that the package authors guarantee neither the accuracy of the lists, nor the accuracy of the match between .bib files and the list. I am aware that the original data source can be found here: https://academic-sexual-misconduct-database.org/

\NeedsTeXFormat{LaTeX2e}[1994/06/01]
\ProvidesPackage{creeps}

\RequirePackage{xcolor}
\RequirePackage{hyperref}

% creeps.txt is the main python file.
\begin{filecontents*}{creeps.txt} 
import sys 
if not filepath.endswith(".bib"):
	filepath = filepath + ".bib"
class keyauthor:
	def __init__(self, keys = [], authors = []):
		self.keys = keys
		self.authors = authors
	def update(self, line):
		if line.strip().startswith("@"):
			self.keys.append(line.strip().split("{")[1].rstrip(',').strip().lower() )
		elif line.strip().split("=")[0].lower().__contains__("author"):
			self.authors.append(line.strip().split("{",1)[1].rsplit("}", 1)[0].split(" and "))
ka = keyauthor()
try:
	with open(filepath) as refs:
		for line in refs:
			ka.update(line)
except:
	print("\PackageError{creeps}{Ooops. Your bibfile was not found}{If your bibfile isn't in the same folder as your .tex file, use a relative filepath.}")
	sys.exit()
if len(ka.authors) == 0:
	sys.exit()
exceptions = [x.strip() for x in exceptions.split(',')]
for x in exceptions:
	try:
		pm = ka.keys.index(x)
		ka.keys.pop(pm)
		ka.authors.pop(pm)
	except:
		pass
single_purpose = ["\\L", "\\l", "\\O", "\\o", "\\AA", "\\aa", "\\AE", "\\ae", "\\OE", "\\oe", "\\ss", "\\i", "\\j"]
sp = {"\\l" : 'l', "\\O" : "O", "\\o" : 'o', "\\aa" : 'a', "\\ae" : 'ae', "\\oe" : 'oe', "\\ss" : 'ss', "\\i" : 'i', "\\j" : 'j'}
multi_purpose = ["\\t", "\\b", "\\d", "\\c", "\\H", "\\v", "\\r", "\\u", '\\"', "\\.", "\\=", "\\~" , "\\^", "\\'", "\\`"]
mp = [x.lower() for x in multi_purpose]
def cleanup(name, mp=mp, sp=sp):
	name = name.replace("{","").replace("}","")
	for l in mp:
		name = name.replace(l,"")
	for k, v in sp.items():
		name = name.replace(k,v)
	return(name)
for i in range(len(ka.authors)):
	ka.authors[i] = [cleanup(x.split(",")[1].strip().lower() + " " + x.split(",")[0].strip().lower())
					if x.__contains__(",") 
					else cleanup(x) 
					for x in ka.authors[i]
					]
names = [item for sublist in ka.authors for item in sublist]
bibd = dict(zip(ka.keys, ka.authors))
entries = []
try:
	with open('asmd.csv', 'r') as file:
		for line in file.readlines():
			entries.append([x.strip() for x in line.split('\t')])
except:
	print("\PackageError{creeps}{Ooops. asmd.csv was not found}{Import it from: https://raw.githubusercontent.com/alistaircameron/creeps/main/asmd.csv}")
	sys.exit()
if update.strip().lower() != 'false':
	from datetime import datetime, date
	if (datetime.strptime(entries[-1][0], "%Y-%m-%d").date() - date.today()).days > 90:
		print("\PackageWarningNoLine{creeps}{You have not updated the offenders database in 3+ months. To do so, navigate to asmd.csv, and click refresh}")
entries = entries[:-1]
offenders, institutions, sources = zip(*entries)
offd = dict(zip(offenders, zip(institutions, sources)))
warnings = set([name for name in names if name in offenders])
if len(warnings) > 0:
	article_ids, institutions, sources = [], [], []
	for w in warnings:
		art_id = []
		for k, v in bibd.items():
			if w in v:
				art_id.append(k)
		article_ids.append(art_id)
		for k, v in offd.items():
			if k == w:
				institutions.append(offd.get(w)[0])
				sources.append(offd.get(w)[1])
	print("\color{red}")
	print("\\begin{itemize}")
	for i in range(len(warnings)):
		message = f"{list(warnings)[i]} ({institutions[i]}; {', '.join(article_ids[i])}) is matched to the database of offenders. For details, see "
		print("\item", message)
		for k, j in enumerate(sources[i].split(";")):
			if k != len(sources[i].split(";")) -1:
				details = f"\href{{{j}}}{{here}}, "
				print(details)
			else:
				details = f"\href{{{j}}}{{here}}."
				print(details)
		print('\n')    
	print("\end{itemize}")
	print("\color{black}")
\end{filecontents*}

\newwrite\creepswriteout
\NewDocumentCommand{\creepsconfigs}{mO{exceptions}O{true}}{
	{
		\gdef\writecreep##1##2##3{
			\immediate\openout\creepswriteout=creepsconfigs.txt\relax
			\immediate\write\creepswriteout{\detokenize{filepath, exceptions, update = "##1", "##2", "##3"}}
			\immediate\closeout\creepswriteout
	}}	
	\writecreep{#1}{#2}{#3}
}

\NewDocumentCommand{\creeps}{mO{exceptions}O{checkforupdates}}{
	\creepsconfigs{#1}[#2][#3]
	\immediate\write18{cat creepsconfigs.txt creeps.txt > creeps.py}
	\input{|python creeps.py}
}
\endinput