fix(batch-9): resolve merge conflict with main after batch 8 merge

This commit is contained in:
mauvehed 2026-03-15 10:00:30 -05:00
commit 6ef1753fff
57 changed files with 1094 additions and 549 deletions

BIN
images/DonaldSkelton.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
images/FelixLindner_1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 691 KiB

BIN
images/FelixLindner_2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

BIN
images/JeromeHeckenkamp.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
images/KellyClark_1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

BIN
images/KellyClark_2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
images/KevinMitnick.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

BIN
images/KrisNova.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
images/RCMartinez.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

BIN
images/RoyDavis_1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 339 KiB

BIN
images/RoyDavis_2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

BIN
images/RoyDavis_3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 MiB

BIN
images/SteveSteinberg.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 KiB

BIN
images/TerryLeifeste.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 445 KiB

15
people/aaronestis.json Normal file
View file

@ -0,0 +1,15 @@
{
"firstname": "Aaron",
"lastname": "Estis",
"handle": "Bogaaron",
"birth": "",
"death": "2022",
"obituary": "",
"issue": "186",
"affiliations": "DEF CON Goon",
"mainimage": "/images/face-silhouette-clipart.png",
"maintext": "<p>Aaron Estis, known as Bogaaron, was a DEF CON Goon and member of the information security community.</p>",
"socialmedialinks": [],
"contributions": [],
"gallery": []
}

24
people/adrianlamo.json Normal file
View file

@ -0,0 +1,24 @@
{
"firstname": "Adrian",
"lastname": "Lamo",
"handle": "",
"birth": "1981",
"death": "2018",
"obituary": "",
"issue": "209",
"affiliations": "2600",
"mainimage": "/images/face-silhouette-clipart.png",
"maintext": "<p>Adrian Lamo was an American threat analyst and hacker. Known as the \"homeless hacker\" for his nomadic lifestyle, Lamo gained attention for breaking into several high-profile computer networks including those of The New York Times, Yahoo!, and Microsoft. He was later known for reporting Chelsea Manning to the U.S. Army in 2010 after Manning confided in him about leaking classified documents to WikiLeaks. Lamo was found dead in a Wichita, Kansas apartment in 2018 at the age of 37.</p>",
"socialmedialinks": [
{
"sitename": "Facebook",
"siteurl": "https://www.facebook.com/LordlOfTheRings"
},
{
"sitename": "Other",
"siteurl": "https://www.npr.org/2019/09/19/760317486/the-mysterious-death-of-the-hacker-who-turned-in-chelsea-manning"
}
],
"contributions": [],
"gallery": []
}

30
people/brammoolenaar.json Normal file
View file

@ -0,0 +1,30 @@
{
"firstname": "Bram",
"lastname": "Moolenaar",
"handle": "",
"birth": "1961",
"death": "2023",
"obituary": "https://groups.google.com/g/vim_announce/c/tWahca9zkt4",
"issue": "236",
"affiliations": "",
"mainimage": "/images/face-silhouette-clipart.png",
"maintext": "<p>Bram Moolenaar was a Dutch software engineer and the creator, maintainer, and benevolent dictator for life of Vim, one of the most widely used text editors in the world. Moolenaar began developing Vim in 1991 as an improvement on the vi editor. He maintained and developed Vim for over 30 years, making it an essential tool for millions of programmers worldwide. Moolenaar was also the founder of the ICCF Holland charity, which supports children in Uganda.</p>",
"socialmedialinks": [
{
"sitename": "Wikipedia",
"siteurl": "https://en.wikipedia.org/wiki/Bram_Moolenaar"
},
{
"sitename": "Other",
"siteurl": "https://www.theregister.com/2023/08/07/bram_moolenaar_obituary/"
}
],
"contributions": [
{
"title": "Vim",
"url": "https://github.com/vim/vim",
"description": "Creator and maintainer of Vim, one of the most popular and enduring text editors, used by millions of developers worldwide."
}
],
"gallery": []
}

15
people/carolanthony.json Normal file
View file

@ -0,0 +1,15 @@
{
"firstname": "Carol",
"lastname": "Anthony",
"handle": "",
"birth": "",
"death": "",
"obituary": "",
"issue": "206",
"affiliations": "ISACA, MTA, Bank of America, Phillips, Protiviti",
"mainimage": "/images/face-silhouette-clipart.png",
"maintext": "<p>Carol Anthony was a cybersecurity professional with experience at ISACA, MTA, Bank of America, Phillips, and Protiviti.</p>",
"socialmedialinks": [],
"contributions": [],
"gallery": []
}

View file

@ -0,0 +1,15 @@
{
"firstname": "Chris",
"lastname": "",
"handle": "The Nightstalker",
"birth": "",
"death": "",
"obituary": "https://web.archive.org/web/20181021094502/http://w3.cultdeadcow.com/cms/nightstalker.html",
"issue": "201",
"affiliations": "Cult of the Dead Cow",
"mainimage": "/images/face-silhouette-clipart.png",
"maintext": "<p>Chris, known as The Nightstalker, was a member of Cult of the Dead Cow (cDc), one of the oldest and most influential hacking groups in the United States.</p>",
"socialmedialinks": [],
"contributions": [],
"gallery": []
}

36
people/chrisscott.json Normal file
View file

@ -0,0 +1,36 @@
{
"firstname": "Chris",
"lastname": "Scott",
"handle": "Cyb3r_Assassin",
"birth": "1983",
"death": "2021",
"obituary": "https://www.clary-glenn.com/obituary/christopher-chris-scott",
"issue": "167",
"affiliations": "FoD, DEF CON Goon, DC615",
"mainimage": "/images/face-silhouette-clipart.png",
"maintext": "<p>Chris Scott, known as Cyb3r_Assassin, was a DEF CON Goon and member of the DC615 Nashville DEF CON group. He was active in the hacker community and contributed through multiple security groups and events.</p>",
"socialmedialinks": [
{
"sitename": "Twitter",
"siteurl": "https://twitter.com/Cyb3r_Assassin"
},
{
"sitename": "Github",
"siteurl": "https://github.com/Cyb3r-Assassin"
},
{
"sitename": "YouTube",
"siteurl": "https://www.youtube.com/channel/UCr-NX4TPEi9JNrwtBJreIwQ"
},
{
"sitename": "WordPress",
"siteurl": "https://cyb3rassassin.wordpress.com/"
},
{
"sitename": "MX Sponsor",
"siteurl": "https://www.mxsponsor.com/riders/chris-a-scott"
}
],
"contributions": [],
"gallery": []
}

40
people/dankaminsky.json Normal file
View file

@ -0,0 +1,40 @@
{
"firstname": "Dan",
"lastname": "Kaminsky",
"handle": "",
"birth": "",
"death": "2021",
"obituary": "https://www.securityweek.com/security-researcher-dan-kaminsky-passes-away",
"issue": "169",
"affiliations": "",
"mainimage": "/images/y3t1_Art-Dan_Kaminsky.png",
"maintext": "<p>Dan Kaminsky was an American computer security researcher. He was a co-founder and chief scientist of WhiteOps (now HUMAN Security). Kaminsky was widely known for his work on DNS security, most notably for discovering a fundamental flaw in the DNS protocol in 2008 that could allow attackers to easily perform cache poisoning attacks on most nameservers. He worked with DNS vendors worldwide in secret to develop a patch, coordinating one of the largest simultaneous security fixes in internet history. Kaminsky was a popular speaker at conferences including DEF CON and Black Hat, known for his wide-ranging curiosity and infectious enthusiasm for exploring security across diverse domains.</p>",
"socialmedialinks": [
{
"sitename": "Twitter",
"siteurl": "https://twitter.com/dakami"
},
{
"sitename": "Wikipedia",
"siteurl": "https://en.wikipedia.org/wiki/Dan_Kaminsky"
}
],
"contributions": [
{
"title": "DNS Cache Poisoning Research",
"url": "https://en.wikipedia.org/wiki/Dan_Kaminsky#DNS_cache_poisoning",
"description": "Discovered a fundamental flaw in the DNS protocol in 2008 that allowed cache poisoning attacks, coordinating a massive multi-vendor patch effort."
},
{
"title": "Bitcoin Flaws Analysis",
"url": "https://www.businessinsider.com/dan-kaminsky-highlights-flaws-bitcoin-2013-4?op=1",
"description": "Research highlighting flaws in Bitcoin."
},
{
"title": "DEF CON Documentary Interview (2012)",
"url": "https://www.youtube.com/watch?v=ZkqY4l6mPtc",
"description": "Full 30-minute interview with Dan Kaminsky about DEF CON, speaking at hacking cons, and what makes them special. Released from the vaults by @textfiles with permission from @thedarktangent."
}
],
"gallery": []
}

20
people/donaldskelton.json Normal file
View file

@ -0,0 +1,20 @@
{
"firstname": "Donald",
"lastname": "Skelton",
"handle": "",
"birth": "1989",
"death": "2023",
"obituary": "",
"issue": "191",
"affiliations": "303",
"mainimage": "/images/DonaldSkelton.webp",
"maintext": "<p>Donald Duane Skelton was a member of the 303 hacking group. He passed away on January 18, 2023, after a prolonged battle with illness. He is survived by his wife and two sons.</p>",
"socialmedialinks": [
{
"sitename": "GoFundMe",
"siteurl": "https://www.gofundme.com/f/donald-dwayne-skelton"
}
],
"contributions": [],
"gallery": []
}

View file

@ -0,0 +1,15 @@
{
"firstname": "Fabian",
"lastname": "Rodriguez",
"handle": "scrotum man",
"birth": "",
"death": "2022",
"obituary": "",
"issue": "185",
"affiliations": "",
"mainimage": "/images/face-silhouette-clipart.png",
"maintext": "<p>Fabian Rodriguez, known as scrotum man, was a member of the hacker community.</p>",
"socialmedialinks": [],
"contributions": [],
"gallery": []
}

30
people/felixlindner.json Normal file
View file

@ -0,0 +1,30 @@
{
"firstname": "Felix",
"lastname": "Lindner",
"handle": "Fx",
"birth": "",
"death": "2026",
"obituary": "https://blog.recurity-labs.com/2026-03-02/Farewell_Felix",
"issue": "308",
"affiliations": "Phenoelit",
"mainimage": "/images/FelixLindner_1.png",
"maintext": "<p>Felix \"FX\" Lindner was a renowned German security researcher and founder of Recurity Labs. He was a member of Phenoelit, a hacking group known for their research on network infrastructure security. FX was a prolific speaker at security conferences worldwide, presenting research on topics ranging from router exploitation to Cisco IOS security. He was widely respected for his deep technical expertise and contributions to understanding vulnerabilities in critical network infrastructure.</p>",
"socialmedialinks": [
{
"sitename": "Website",
"siteurl": "https://phenoelit.de/"
},
{
"sitename": "Other",
"siteurl": "https://infocondb.org/presenter/felix-lindner-fx"
}
],
"contributions": [],
"gallery": [
{
"url": "/images/FelixLindner_2.png",
"title": "Felix Lindner (FX)",
"caption": "Photo of Felix Lindner shared by The Dark Tangent"
}
]
}

20
people/genekan.json Normal file
View file

@ -0,0 +1,20 @@
{
"firstname": "Gene",
"lastname": "Kan",
"handle": "",
"birth": "1976",
"death": "2002",
"obituary": "",
"issue": "163",
"affiliations": "",
"mainimage": "/images/face-silhouette-clipart.png",
"maintext": "<p>Gene Kan was a computer programmer and open source advocate best known for his work on Gnutella, the peer-to-peer file sharing network. He was an early and prominent developer of the Gnutella protocol and its open source implementations, and became a visible spokesperson for the peer-to-peer movement. Kan was also a contributor to various open source projects and a frequent speaker on decentralized networking technology.</p>",
"socialmedialinks": [
{
"sitename": "Wikipedia",
"siteurl": "https://en.wikipedia.org/wiki/Gene_Kan"
}
],
"contributions": [],
"gallery": []
}

20
people/glenneccard.json Normal file
View file

@ -0,0 +1,20 @@
{
"firstname": "Glenn",
"lastname": "Eccard",
"handle": "V310C1TY",
"birth": "",
"death": "2021",
"obituary": "",
"issue": "183",
"affiliations": "Hackers For Charity",
"mainimage": "/images/face-silhouette-clipart.png",
"maintext": "<p>Glenn Eccard, known as V310C1TY, was a member of Hackers For Charity and the broader information security community.</p>",
"socialmedialinks": [
{
"sitename": "Twitter",
"siteurl": "https://twitter.com/V310C1TY/"
}
],
"contributions": [],
"gallery": []
}

View file

@ -0,0 +1,20 @@
{
"firstname": "Ilya",
"lastname": "Zhitomirskiy",
"handle": "",
"birth": "1989",
"death": "2011",
"obituary": "",
"issue": "164",
"affiliations": "",
"mainimage": "/images/face-silhouette-clipart.png",
"maintext": "<p>Ilya Zhitomirskiy was a software developer and co-founder of Diaspora, a decentralized social networking platform created as a privacy-aware alternative to Facebook. While a student at New York University, Zhitomirskiy and three classmates launched a successful Kickstarter campaign in 2010 to fund development of the open source social network. The project drew widespread attention as a response to growing concerns about privacy on centralized social media platforms.</p>",
"socialmedialinks": [
{
"sitename": "Other",
"siteurl": "https://www.forbes.com/sites/meghancasserly/2011/11/16/ilya-zhitomirskiy-diaspora-suicide-speculation-depression-stress-anxiety/"
}
],
"contributions": [],
"gallery": []
}

20
people/jamesdolan.json Normal file
View file

@ -0,0 +1,20 @@
{
"firstname": "James",
"lastname": "Dolan",
"handle": "",
"birth": "1981",
"death": "2017",
"obituary": "",
"issue": "162",
"affiliations": "",
"mainimage": "/images/face-silhouette-clipart.png",
"maintext": "<p>James Dolan was a computer security expert and Marine veteran. He was a co-creator of SecureDrop, the open-source whistleblower submission system, alongside Aaron Swartz and Kevin Poulsen. SecureDrop is used by major news organizations worldwide to securely receive documents from anonymous sources.</p>",
"socialmedialinks": [
{
"sitename": "Wikipedia",
"siteurl": "https://en.wikipedia.org/wiki/James_Dolan_(computer_security_expert)"
}
],
"contributions": [],
"gallery": []
}

35
people/jasonsnitker.json Normal file
View file

@ -0,0 +1,35 @@
{
"firstname": "Jason",
"lastname": "Snitker",
"handle": "Parmaster",
"birth": "",
"death": "2026",
"obituary": "",
"issue": "307",
"affiliations": "",
"mainimage": "/images/face-silhouette-clipart.png",
"maintext": "<p>Jason Snitker, known as Parmaster, was a member of the hacker and information security community. His story was featured on the Darknet Diaries podcast.</p>",
"socialmedialinks": [
{
"sitename": "Bluesky",
"siteurl": "https://bsky.app/profile/did:plc:low75hwexu2oc5v2rj5p2lbu"
}
],
"contributions": [
{
"title": "Darknet Diaries Episode 169",
"url": "https://darknetdiaries.com/transcript/169/",
"description": "Jason's story featured on the Darknet Diaries podcast."
}
],
"gallery": [
{
"url": "https://fxtwitter.com/WeldPond/status/2024682841292898378",
"caption": "WeldPond memorial tweet"
},
{
"url": "https://www.youtube.com/watch?v=BkeXk9rBBrs&t=1s",
"caption": "YouTube video"
}
]
}

View file

@ -0,0 +1,28 @@
{
"firstname": "Jerome",
"lastname": "Heckenkamp",
"handle": "Sk8",
"birth": "1979",
"death": "2016",
"obituary": "https://www.legacy.com/funeral-homes/obituaries/name/jerome-heckenkamp-obituary?pid=178007168&v=batesville",
"issue": "208",
"affiliations": "",
"mainimage": "/images/JeromeHeckenkamp.jpg",
"maintext": "<p>Jerome Heckenkamp, known as Sk8 (also linked to the handle MagicFX), was a hacker who gained notoriety for unauthorized access to computer networks at several organizations including Qualcomm, eBay, and others. His case became notable in computer law, involving questions about search and seizure of computer evidence. He was defended by Jennifer Granick of the Stanford Cyberlaw Clinic.</p>",
"socialmedialinks": [
{
"sitename": "Memorial Site",
"siteurl": "https://www.jeromeheckenkamp.com/"
},
{
"sitename": "IT Law Wiki",
"siteurl": "https://itlaw.fandom.com/wiki/U.S._v._Heckenkamp"
},
{
"sitename": "Free Sk8 Archive",
"siteurl": "https://web.archive.org/web/20031008121704/http://www.freesk8.com/"
}
],
"contributions": [],
"gallery": []
}

20
people/kellyclark.json Normal file
View file

@ -0,0 +1,20 @@
{
"firstname": "Kelly",
"lastname": "Clark",
"handle": "",
"birth": "",
"death": "",
"obituary": "",
"issue": "204",
"affiliations": "",
"mainimage": "/images/KellyClark_1.jpg",
"maintext": "<p>Kelly Clark was a member of the hacker and information security community.</p>",
"socialmedialinks": [],
"contributions": [],
"gallery": [
{
"url": "/images/KellyClark_2.jpg",
"caption": ""
}
]
}

30
people/kellytodd.json Normal file
View file

@ -0,0 +1,30 @@
{
"firstname": "Kelly",
"lastname": "Todd",
"handle": "Lyger",
"birth": "",
"death": "2022",
"obituary": "",
"issue": "198",
"affiliations": "Attrition",
"mainimage": "/images/face-silhouette-clipart.png",
"maintext": "<p>Kelly Todd, known as Lyger, was a member of the Attrition.org crew. He was active in the information security community and contributed to security research and documentation efforts through Attrition.</p>",
"socialmedialinks": [
{
"sitename": "Twitter",
"siteurl": "https://twitter.com/lazlo_d_plumber"
},
{
"sitename": "Website",
"siteurl": "https://attrition.org/~lyger/"
}
],
"contributions": [
{
"title": "Tribute Video",
"url": "https://www.youtube.com/watch?v=zOH5jEK4dhk",
"description": "Video tribute to Kelly Todd (Lyger)."
}
],
"gallery": []
}

24
people/kevinestis.json Normal file
View file

@ -0,0 +1,24 @@
{
"firstname": "Kevin",
"lastname": "Estis",
"handle": "",
"birth": "",
"death": "2021",
"obituary": "",
"issue": "165",
"affiliations": "DEF CON Goon",
"mainimage": "/images/face-silhouette-clipart.png",
"maintext": "<p>Kevin Estis was a member of the information security community and a DEF CON Goon.</p>",
"socialmedialinks": [
{
"sitename": "Twitter",
"siteurl": "https://twitter.com/kevinestis"
},
{
"sitename": "GoFundMe",
"siteurl": "https://www.gofundme.com/f/aid-for-kevin-estis-family-and-pets"
}
],
"contributions": [],
"gallery": []
}

40
people/kevinmitnick.json Normal file
View file

@ -0,0 +1,40 @@
{
"firstname": "Kevin",
"lastname": "Mitnick",
"handle": "Condor",
"birth": "1963",
"death": "2023",
"obituary": "https://www.dignitymemorial.com/obituaries/las-vegas-nv/kevin-mitnick-11371668",
"issue": "197",
"affiliations": "",
"mainimage": "/images/KevinMitnick.webp",
"maintext": "<p>Kevin David Mitnick was an American computer security consultant, author, and convicted hacker. Once the FBI's most-wanted computer criminal, Mitnick was known for his social engineering skills and his ability to gain unauthorized access to computer systems and networks. After serving five years in prison, he became a security consultant and public speaker. He authored several books including <em>The Art of Deception</em>, <em>The Art of Intrusion</em>, and his autobiography <em>Ghost in the Wires</em>. Mitnick founded Mitnick Security Consulting and KnowBe4's Chief Hacking Officer.</p>",
"socialmedialinks": [
{
"sitename": "Twitter",
"siteurl": "https://twitter.com/kevinmitnick"
},
{
"sitename": "Wikipedia",
"siteurl": "https://en.wikipedia.org/wiki/Kevin_Mitnick"
}
],
"contributions": [
{
"title": "CNN Obituary",
"url": "https://www.cnn.com/2023/07/21/us/computer-hacker-kevin-mitnick-obit/index.html",
"description": "CNN obituary for Kevin Mitnick."
},
{
"title": "BBC Obituary",
"url": "https://www.bbc.com/news/world-us-canada-66263235",
"description": "BBC obituary for Kevin Mitnick."
},
{
"title": "AP News Obituary",
"url": "https://apnews.com/article/mitnick-hacker-ghost-wires-cybersecurity-social-engineering-5648301b615635cb4c781f0c220681d9",
"description": "Associated Press obituary for Kevin Mitnick."
}
],
"gallery": []
}

20
people/kevinriggins.json Normal file
View file

@ -0,0 +1,20 @@
{
"firstname": "Kevin",
"lastname": "Riggins",
"handle": "",
"birth": "",
"death": "2022",
"obituary": "https://www.hamiltonsfuneralhome.com/services/services_detail.aspx?rid=62762",
"issue": "188",
"affiliations": "",
"mainimage": "/images/face-silhouette-clipart.png",
"maintext": "<p>Kevin William Riggins was a member of the information security community.</p>",
"socialmedialinks": [
{
"sitename": "Twitter",
"siteurl": "https://twitter.com/kriggins"
}
],
"contributions": [],
"gallery": []
}

40
people/krisnova.json Normal file
View file

@ -0,0 +1,40 @@
{
"firstname": "Kris",
"lastname": "Nova",
"handle": "Kris Nova",
"birth": "1986",
"death": "2023",
"obituary": "https://www.sportskeeda.com/pop-culture/news-kris-nova-accident-tributes-pour-github-engineer-passes-away",
"issue": "251",
"affiliations": "GitHub, Cloud Native Computing Foundation",
"mainimage": "/images/KrisNova.jpg",
"maintext": "<p>Kris Nova was an author, engineer, computer scientist, and alpinist best known for her work on Linux, Kubernetes, and Aurae. She was a Senior Developer Advocate for Heptio and an ambassador for the Cloud Native Computing Foundation. Prior to Heptio, Nova worked as a developer advocate for Microsoft and as an engineer on Kubernetes in Azure. She was a prolific open source contributor and the founder of Hachyderm, a Mastodon instance for technology professionals. Nova was also an avid mountaineer and YouTube host.</p>",
"socialmedialinks": [
{
"sitename": "Twitter",
"siteurl": "https://twitter.com/krisnova"
},
{
"sitename": "Github",
"siteurl": "https://github.com/krisnova"
},
{
"sitename": "Website",
"siteurl": "https://krisnova.net/"
},
{
"sitename": "Hachyderm",
"siteurl": "https://hachyderm.io/@nova"
},
{
"sitename": "YouTube",
"siteurl": "https://www.youtube.com/@KrisNovaLive"
},
{
"sitename": "Twitch",
"siteurl": "https://twitch.tv/krisnova"
}
],
"contributions": [],
"gallery": []
}

15
people/mariamoraru.json Normal file
View file

@ -0,0 +1,15 @@
{
"firstname": "Maria",
"lastname": "Moraru",
"handle": "",
"birth": "",
"death": "",
"obituary": "",
"issue": "205",
"affiliations": "",
"mainimage": "/images/face-silhouette-clipart.png",
"maintext": "<p>Maria Moraru was a member of the hacker and information security community.</p>",
"socialmedialinks": [],
"contributions": [],
"gallery": []
}

26
people/markshapiro.json Normal file
View file

@ -0,0 +1,26 @@
{
"firstname": "Mark",
"lastname": "Shapiro",
"handle": "gntlmnguardian",
"birth": "1979",
"death": "2020",
"obituary": "https://www.dignitymemorial.com/obituaries/falls-church-va/mark-shapiro-9170264",
"issue": "158",
"affiliations": "",
"mainimage": "/images/face-silhouette-clipart.png",
"maintext": "<p>Mark Edward Shapiro was a cybersecurity professional employed at Jacobs Critical Mission Solutions as a Project Manager of cybersecurity, intelligence, and information operations for the Securities and Exchange Commission in Washington, D.C. Only weeks prior to his death, Mark had completed his first cybersecurity industry convention presentation, giving a featured talk at BSides NoVA on \"Democratizing Intelligence.\" He also trained in Executive Protection and Physical Security, and often assisted in this capacity at media conventions.</p>",
"socialmedialinks": [
{
"sitename": "Twitter",
"siteurl": "https://twitter.com/gntlmnguardian"
}
],
"contributions": [
{
"title": "BSides NoVA 2020 - Democratized Intelligence: Promises and Pitfalls",
"url": "https://www.youtube.com/watch?v=qKWQyk7Xypw&list=PLrwRJhfJmJRjleUT5gEBno3S5csqNIhFo&index=6&t=320s",
"description": "A talk on the advancement of privatized intelligence capacity, examining how individuals can stand up a functional intelligence apparatus and the hazards of doing so from analytical and operational perspectives."
}
],
"gallery": []
}

15
people/michaelpark.json Normal file
View file

@ -0,0 +1,15 @@
{
"firstname": "Michael",
"lastname": "Park",
"handle": "Hosaka",
"birth": "",
"death": "2023",
"obituary": "",
"issue": "199",
"affiliations": "r00t",
"mainimage": "/images/face-silhouette-clipart.png",
"maintext": "<p>Michael Park, known as Hosaka, was a member of the r00t hacking group.</p>",
"socialmedialinks": [],
"contributions": [],
"gallery": []
}

37
people/mikemurray.json Normal file
View file

@ -0,0 +1,37 @@
{
"firstname": "Mike",
"lastname": "Murray",
"handle": "",
"birth": "1976",
"death": "2022",
"obituary": "https://jamesreidfuneralhome.com/tribute/details/14089/Michael-Murray/obituary.html",
"issue": "187",
"affiliations": "",
"mainimage": "/images/face-silhouette-clipart.png",
"maintext": "<p>Mike Murray was a cybersecurity professional and the founder of Scope Security. He was known for his work in the information security industry and was active in the security community.</p>",
"socialmedialinks": [
{
"sitename": "Twitter",
"siteurl": "https://twitter.com/mmurray"
},
{
"sitename": "Instagram",
"siteurl": "https://www.instagram.com/michael_l_murray/"
},
{
"sitename": "Scope Security",
"siteurl": "https://scopesecurity.com/"
}
],
"contributions": [],
"gallery": [
{
"url": "https://www.instagram.com/p/CcJDPCevFBg/?igshid=YmMyMTA2M2Y=",
"caption": "Instagram memorial post"
},
{
"url": "https://twitter.com/scopesecurity_/status/1512927318481723394",
"caption": "Scope Security memorial tweet"
}
]
}

20
people/ozzieosband.json Normal file
View file

@ -0,0 +1,20 @@
{
"firstname": "Ozzie",
"lastname": "Osband",
"handle": "Cheshire Catalyst",
"birth": "",
"death": "2023",
"obituary": "https://talkoftitusville.com/2023/08/06/ozzie-osband-originator-of-3-2-1-telephone-area-code-and-rocket-hobo-passes-away-at-72/",
"issue": "241",
"affiliations": "",
"mainimage": "/images/face-silhouette-clipart.png",
"maintext": "<p>Ozzie Osband, known as Cheshire Catalyst, was a phreaker and hacker active in the early days of the hacking scene. He was the editor of the Technology Assistance Program (TAP) newsletter, a successor to the YIPL (Youth International Party Line) newsletter that was a key publication in the phone phreaking community. He was known for originating the 321 telephone area code and was sometimes referred to as the Rocket Hobo.</p>",
"socialmedialinks": [
{
"sitename": "LinkedIn",
"siteurl": "https://www.linkedin.com/in/ozzie321/"
}
],
"contributions": [],
"gallery": []
}

28
people/rcmartinez.json Normal file
View file

@ -0,0 +1,28 @@
{
"firstname": "RC",
"lastname": "Martinez",
"handle": "GodFix",
"birth": "",
"death": "2021",
"obituary": "https://www.skydogcon.com/2021/04/in-memoriam-godfix.html",
"issue": "168",
"affiliations": "DEF CON Goon, SkyDogCon Staff",
"mainimage": "/images/RCMartinez.jpg",
"maintext": "<p>RC Martinez, known as GodFix, was a DEF CON Goon and SkyDogCon staff member. Described as the \"Fixer of Itches\" and \"Finder of All-the-things,\" he was a staff member for five different conferences since 2007. When not filling roles at a con, he worked as a Senior Infrastructure Engineer. RC was known for his welcoming nature, always greeting people with a hug and a smile. He lost his battle with pneumonia caused by COVID-19 on April 17, 2021, leaving behind his wife Debra and two children.</p>",
"socialmedialinks": [
{
"sitename": "Twitter",
"siteurl": "https://twitter.com/GodFix"
},
{
"sitename": "GoFundMe",
"siteurl": "https://gofund.me/b33cca5a"
},
{
"sitename": "Facebook Memorial",
"siteurl": "https://www.facebook.com/132688066753041/posts/4140135462674928/"
}
],
"contributions": [],
"gallery": []
}

20
people/reverendrat.json Normal file
View file

@ -0,0 +1,20 @@
{
"firstname": "",
"lastname": "",
"handle": "Reverend Rat",
"birth": "",
"death": "",
"obituary": "",
"issue": "184",
"affiliations": "",
"mainimage": "/images/face-silhouette-clipart.png",
"maintext": "<p>Reverend Rat was a member of the hacker and information security community.</p>",
"socialmedialinks": [
{
"sitename": "Twitter Memorial",
"siteurl": "https://twitter.com/marcwrogers/status/1438186471907737600"
}
],
"contributions": [],
"gallery": []
}

15
people/richardbatka.json Normal file
View file

@ -0,0 +1,15 @@
{
"firstname": "Richard",
"lastname": "Batka",
"handle": "Master Chemist",
"birth": "",
"death": "2023",
"obituary": "",
"issue": "200",
"affiliations": "",
"mainimage": "/images/face-silhouette-clipart.png",
"maintext": "<p>Richard Batka, known as Master Chemist, was a member of the hacker and information security community.</p>",
"socialmedialinks": [],
"contributions": [],
"gallery": []
}

49
people/roydavis.json Normal file
View file

@ -0,0 +1,49 @@
{
"firstname": "Roy",
"lastname": "Davis",
"handle": "Hack_All_Things",
"birth": "1968",
"death": "2025",
"obituary": "",
"issue": "295",
"affiliations": "",
"mainimage": "/images/RoyDavis_1.png",
"maintext": "<p>Roy Davis, known as Hack All Things, was a security researcher and hacker. He was known for his engaging conference talks, including a notable presentation on buying and hacking into an ATM. Roy challenged the industry to think about alternative approaches to measuring vulnerability severity through the VISS (Vulnerability Impact Scoring System) project at Zoom. He was active in the bug bounty community and participated in events such as H1-4420.</p>",
"socialmedialinks": [
{
"sitename": "Twitter",
"siteurl": "https://x.com/Hack_All_Things"
},
{
"sitename": "LinkedIn",
"siteurl": "https://www.linkedin.com/in/roy-davis/"
}
],
"contributions": [
{
"title": "ATM Hacking Talk",
"url": "https://www.youtube.com/watch?v=9cG-JL0LHYw",
"description": "Conference talk on buying an ATM and hacking into it."
},
{
"title": "VISS - Vulnerability Impact Scoring System",
"url": "https://viss.zoom.com/",
"description": "An alternative approach to measuring vulnerability severity developed at Zoom."
},
{
"title": "Zoom H1-4420 Event Blog Post",
"url": "https://www.zoom.com/en/blog/zoom-hackerone-h1-4420-event-2023/",
"description": "Roy's blog post about the Zoom HackerOne H1-4420 event in London 2023."
}
],
"gallery": [
{
"url": "/images/RoyDavis_2.png",
"caption": "Roy Davis at H1-4420 2023 in London"
},
{
"url": "/images/RoyDavis_3.png",
"caption": "Roy Davis at Infosecurity Europe 2023 in London"
}
]
}

View file

@ -0,0 +1,15 @@
{
"firstname": "Steve",
"lastname": "Steinberg",
"handle": "Frank Drake",
"birth": "1970",
"death": "2020",
"obituary": "https://boingboing.net/2020/10/09/steve-steinberg-hacker-writer-friend-1970-2020.html",
"issue": "160",
"affiliations": "",
"mainimage": "/images/SteveSteinberg.jpg",
"maintext": "<p>Steve Steinberg, also known as Frank Drake, was a hacker and writer. He was the publisher of WORM and Intertek, notable hacker-era publications. He was remembered as \"a true hacker\" by those who knew him.</p>",
"socialmedialinks": [],
"contributions": [],
"gallery": []
}

20
people/terryleifeste.json Normal file
View file

@ -0,0 +1,20 @@
{
"firstname": "Terry",
"lastname": "Leifeste",
"handle": "phliKtid",
"birth": "1969",
"death": "2026",
"obituary": "https://www.crespoandjirrels.com/obituaries/Terry-Lynn-Leifeste?obId=47082591",
"issue": "303",
"affiliations": "DEF CON Goon SpeakerOps",
"mainimage": "/images/TerryLeifeste.jpg",
"maintext": "<p>Terry Lynn Leifeste, known as phliKtid, was a DEF CON Goon who worked in SpeakerOps, helping coordinate speakers and presentations at the conference.</p>",
"socialmedialinks": [
{
"sitename": "LinkedIn Memorial",
"siteurl": "https://www.linkedin.com/posts/activity-7418849222084542464-BktK"
}
],
"contributions": [],
"gallery": []
}

20
people/timskorick.json Normal file
View file

@ -0,0 +1,20 @@
{
"firstname": "Tim",
"lastname": "Skorick",
"handle": "Timmah",
"birth": "",
"death": "2026",
"obituary": "",
"issue": "304",
"affiliations": "303",
"mainimage": "/images/face-silhouette-clipart.png",
"maintext": "<p>Tim Skorick, known as Timmah, was a member of the 303 hacking group and the information security community.</p>",
"socialmedialinks": [
{
"sitename": "GoFundMe",
"siteurl": "https://www.gofundme.com/f/support-for-the-skorick-family"
}
],
"contributions": [],
"gallery": []
}

33
people/trycatchhcf.json Normal file
View file

@ -0,0 +1,33 @@
{
"firstname": "Joe",
"lastname": "",
"handle": "TryCatchHCF",
"birth": "",
"death": "2023",
"obituary": "",
"issue": "190",
"affiliations": "",
"mainimage": "/images/face-silhouette-clipart.png",
"maintext": "<p>Joe, known as TryCatchHCF, was a security researcher and open source developer. He was known in the hacker community for his security tools and contributions on GitHub. He passed away peacefully in his sleep after a battle with cancer, surrounded by people he loved. He was remembered as a private but deeply caring person who enjoyed birds, ethics discussions, and the outdoors.</p>",
"socialmedialinks": [
{
"sitename": "Twitter",
"siteurl": "https://twitter.com/TryCatchHCF"
},
{
"sitename": "Github",
"siteurl": "https://github.com/TryCatchHCF/"
}
],
"contributions": [],
"gallery": [
{
"url": "https://twitter.com/rotate26chars/status/1612242052955398144",
"caption": "Memorial thread by rotate26chars"
},
{
"url": "https://twitter.com/Flex_Capacitor/status/1612551832261238794",
"caption": "Remembrance from Joe's child"
}
]
}

31
people/vijaygill.json Normal file
View file

@ -0,0 +1,31 @@
{
"firstname": "Vijay",
"lastname": "Gill",
"handle": "",
"birth": "1971",
"death": "2022",
"obituary": "https://www.legacy.com/us/obituaries/name/vijay-gill-obituary?id=36166748",
"issue": "232",
"affiliations": "IAB, IETF, NANOG",
"mainimage": "/images/face-silhouette-clipart.png",
"maintext": "<p>Vijay Gill was a prolific network engineer employed by various ISPs and hyperscale networks including UUNet, AOL, Microsoft, Google, and Salesforce. He was a contributor to the wider Internet community through his involvement with the IETF, IAB, and NANOG, and co-authored multiple RFCs related to Internet architecture and routing.</p>",
"socialmedialinks": [
{
"sitename": "LinkedIn",
"siteurl": "https://www.linkedin.com/in/vgill/"
}
],
"contributions": [
{
"title": "RFC 3582 - Goals for IPv6 Site-Multihoming Architectures",
"url": "https://www.rfc-editor.org/rfc/rfc3582.txt",
"description": "Co-authored RFC defining goals for IPv6 site-multihoming architectures."
},
{
"title": "RFC 4451 - BGP MULTI_EXIT_DISC (MED) Considerations",
"url": "https://www.rfc-editor.org/rfc/rfc4451.txt",
"description": "Co-authored RFC on BGP MED attribute considerations for network routing."
}
],
"gallery": []
}

15
people/williamcopley.json Normal file
View file

@ -0,0 +1,15 @@
{
"firstname": "William",
"lastname": "Copley",
"handle": "The Pull",
"birth": "",
"death": "2022",
"obituary": "",
"issue": "189",
"affiliations": "cDc",
"mainimage": "/images/face-silhouette-clipart.png",
"maintext": "<p>William Andrew \"Drew\" Copley, known as The Pull, was a founding member of Hacktivismo and a respected friend of Cult of the Dead Cow (cDc). He was a tireless advocate of internet freedom and a valued security researcher. The Pull was a ridiculously smart guy with a great sense of humor and exemplary work ethic. He was dedicated to making a mark for the better, was a core contributor to the hacktivist movement, writing a steganography app called Camera/Shy. He died of cancer in 2022.</p>",
"socialmedialinks": [],
"contributions": [],
"gallery": []
}

View file

@ -0,0 +1,26 @@
{
"firstname": "Yonathan",
"lastname": "Klijnsma",
"handle": "ydklijnsma",
"birth": "",
"death": "2021",
"obituary": "",
"issue": "161",
"affiliations": "",
"mainimage": "/images/face-silhouette-clipart.png",
"maintext": "<p>Yonathan Klijnsma was a security researcher known for his work in threat intelligence and cybersecurity. He passed away due to cancer in January 2021.</p>",
"socialmedialinks": [
{
"sitename": "Twitter",
"siteurl": "https://twitter.com/ydklijnsma"
}
],
"contributions": [
{
"title": "Cybersecurity Interviews Podcast",
"url": "https://cybersecurityinterviews.com/episodes/61-yonathan-klijnsma-get-compromised-get-compromised/",
"description": "Episode 61 - Yonathan Klijnsma - Get Compromised, Get Compromised"
}
],
"gallery": []
}

View file

@ -228,6 +228,158 @@
"displayname": "Ben Preston (Veruus)",
"filename": "benpreston"
},
{
"displayname": "Dan Kaminsky",
"filename": "dankaminsky"
},
{
"displayname": "Kevin Mitnick (Condor)",
"filename": "kevinmitnick"
},
{
"displayname": "Adrian Lamo",
"filename": "adrianlamo"
},
{
"displayname": "Bram Moolenaar",
"filename": "brammoolenaar"
},
{
"displayname": "Kris Nova",
"filename": "krisnova"
},
{
"displayname": "Kelly Todd (Lyger)",
"filename": "kellytodd"
},
{
"displayname": "Michael Park (Hosaka)",
"filename": "michaelpark"
},
{
"displayname": "Richard Batka (Master Chemist)",
"filename": "richardbatka"
},
{
"displayname": "Ozzie Osband (Cheshire Catalyst)",
"filename": "ozzieosband"
},
{
"displayname": "Felix Lindner (Fx)",
"filename": "felixlindner"
},
{
"displayname": "Mark Shapiro (gntlmnguardian)",
"filename": "markshapiro"
},
{
"displayname": "Steve Steinberg (Frank Drake)",
"filename": "stevesteinberg"
},
{
"displayname": "Yonathan Klijnsma",
"filename": "yonathanklijnsma"
},
{
"displayname": "James Dolan",
"filename": "jamesdolan"
},
{
"displayname": "Gene Kan",
"filename": "genekan"
},
{
"displayname": "Ilya Zhitomirskiy",
"filename": "ilyazhitomirskiy"
},
{
"displayname": "Kevin Estis",
"filename": "kevinestis"
},
{
"displayname": "Chris Scott (Cyb3r_Assassin)",
"filename": "chrisscott"
},
{
"displayname": "RC Martinez (GodFix)",
"filename": "rcmartinez"
},
{
"displayname": "Glenn Eccard (V310C1TY)",
"filename": "glenneccard"
},
{
"displayname": "Fabian Rodriguez",
"filename": "fabianrodriguez"
},
{
"displayname": "Aaron Estis (Bogaaron)",
"filename": "aaronestis"
},
{
"displayname": "Mike Murray",
"filename": "mikemurray"
},
{
"displayname": "Kevin William Riggins",
"filename": "kevinriggins"
},
{
"displayname": "William Andrew Copley (The Pull)",
"filename": "williamcopley"
},
{
"displayname": "TryCatchHCF (Joe)",
"filename": "trycatchhcf"
},
{
"displayname": "Donald Duane Skelton",
"filename": "donaldskelton"
},
{
"displayname": "Kelly Clark",
"filename": "kellyclark"
},
{
"displayname": "Maria Moraru",
"filename": "mariamoraru"
},
{
"displayname": "Carol Anthony",
"filename": "carolanthony"
},
{
"displayname": "Jerome Heckenkamp (Sk8)",
"filename": "jeromeheckenkamp"
},
{
"displayname": "Vijay Gill",
"filename": "vijaygill"
},
{
"displayname": "Roy Davis (Hack All Things)",
"filename": "roydavis"
},
{
"displayname": "Terry Leifeste (phliKtid)",
"filename": "terryleifeste"
},
{
"displayname": "Tim Skorick (Timmah)",
"filename": "timskorick"
},
{
"displayname": "Jason Snitker (Parmaster)",
"filename": "jasonsnitker"
},
{
"displayname": "Reverend Rat",
"filename": "reverendrat"
},
{
"displayname": "Chris (The Nightstalker)",
"filename": "chrisnightstalker"
},
{
"displayname": "AP Delchi",
"filename": "apdelchi"

View file

@ -1,32 +0,0 @@
github:
repo: restincode/restincode
# Token will be read from GITHUB_TOKEN environment variable
archive:
archive_org_enabled: true
archive_today_enabled: true
processing:
dry_run: false
max_concurrent: 5
paths:
people_dir: people
images_dir: images
peoplelist: peoplelist.json
template: people/_template.json
logs_dir: logs
priorities:
# High-profile people to process first
high_profile:
- Kevin David Mitnick
- Dan Kaminsky
- Bram Moolenaar
- Adrian Lamo
- Kris Nova
- Kelly Todd
- Michael Park
- Richard Batka
- Chris Hurley
- Ozzie Osband

View file

@ -1,514 +0,0 @@
#!/usr/bin/env python3
"""
RestInCode Issue Processing Automation
Processes GitHub Issues to create memorial JSON files and submit PRs.
"""
import os
import sys
import json
import re
import logging
import subprocess
import yaml
import argparse
from datetime import datetime
from pathlib import Path
from typing import Dict, List, Optional, Tuple
class IssueProcessor:
"""Main class for processing GitHub Issues into memorial entries."""
def __init__(self, config_path: str = "scripts/config.yaml"):
"""Initialize the processor with configuration."""
self.load_config(config_path)
self.setup_logging()
self.repo_root = Path.cwd()
def load_config(self, config_path: str):
"""Load configuration from YAML file."""
with open(config_path, 'r') as f:
self.config = yaml.safe_load(f)
def setup_logging(self):
"""Configure logging to file and console."""
log_dir = Path(self.config['paths']['logs_dir'])
log_dir.mkdir(exist_ok=True)
log_file = log_dir / f"processing_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log"
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler(log_file),
logging.StreamHandler(sys.stdout)
]
)
self.logger = logging.getLogger(__name__)
self.logger.info("Issue Processor initialized")
def fetch_issues(self, label: str) -> List[Dict]:
"""
Fetch issues from GitHub using gh CLI.
Args:
label: Issue label to filter by ('Add Person' or 'Add Data')
Returns:
List of issue dictionaries
"""
self.logger.info(f"Fetching issues with label: {label}")
cmd = [
'gh', 'issue', 'list',
'--repo', self.config['github']['repo'],
'--label', label,
'--limit', '100',
'--json', 'number,title,body,author,comments,labels,url',
'--state', 'open'
]
try:
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
issues = json.loads(result.stdout)
self.logger.info(f"Fetched {len(issues)} issues with label '{label}'")
return issues
except subprocess.CalledProcessError as e:
self.logger.error(f"Failed to fetch issues: {e}")
return []
def fetch_issue_details(self, issue_number: int) -> Optional[Dict]:
"""
Fetch detailed issue information including comments.
Args:
issue_number: GitHub issue number
Returns:
Issue dictionary with full details
"""
self.logger.info(f"Fetching details for issue #{issue_number}")
cmd = [
'gh', 'issue', 'view', str(issue_number),
'--repo', self.config['github']['repo'],
'--json', 'number,title,body,author,comments,labels,url'
]
try:
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
issue = json.loads(result.stdout)
return issue
except subprocess.CalledProcessError as e:
self.logger.error(f"Failed to fetch issue #{issue_number}: {e}")
return None
def parse_issue_template(self, issue_body: str) -> Dict[str, str]:
"""
Parse issue template to extract structured data.
Args:
issue_body: Raw markdown body of the issue
Returns:
Dictionary of extracted fields
"""
data = {}
if not issue_body:
return data
# Define field patterns to extract (handle both - and * bullets)
# Use [^\n\r]+ to match everything except newlines
patterns = {
'firstname': r'[*-]\s*First name:\s*([^\n\r]+)',
'lastname': r'[*-]\s*Last name:\s*([^\n\r]+)',
'handle': r'[*-]\s*Handle:\s*([^\n\r]+)',
'birth': r'[*-]\s*Birth Year:\s*([^\n\r]+)',
'death': r'[*-]\s*Death Year:\s*([^\n\r]+)',
'obituary': r'[*-]\s*Link to Obituary:\s*([^\n\r]+)',
'affiliations': r'[*-]\s*Group Affiliations:\s*([^\n\r]+)',
'mainimage_url': r'[*-]\s*URL to main photo[^:]*:\s*([^\n\r]+)',
'description': r'[*-]\s*Description of person[^:]*:\s*([^\n\r]+)',
'twitter': r'[*-]\s*Twitter:\s*([^\n\r]+)',
'github': r'[*-]\s*Github:\s*([^\n\r]+)',
'linkedin': r'[*-]\s*LinkedIn:\s*([^\n\r]+)',
'facebook': r'[*-]\s*Facebook:\s*([^\n\r]+)',
'wikipedia': r'[*-]\s*Wikipedia:\s*([^\n\r]+)',
'other_url': r'[*-]\s*Other:\s*([^\n\r]+)',
}
for field, pattern in patterns.items():
match = re.search(pattern, issue_body, re.IGNORECASE)
if match:
value = match.group(1).strip()
# Clean up empty values and values that are just bullets
if value and value not in ['', 'N/A', 'n/a', 'None', 'none'] and not value.startswith('*') and not value.startswith('-'):
data[field] = value
# Extract contributions (can be multiple)
contributions = []
contrib_pattern = r'[*-]\s*Project name:\s*(.+?)[\n\r]+[*-]\s*Project URL:\s*(.+?)[\n\r]+[*-]\s*Project Description:\s*(.+?)(?=\n[*-]|\n\*\*|$)'
for match in re.finditer(contrib_pattern, issue_body, re.IGNORECASE | re.DOTALL):
title = match.group(1).strip()
url = match.group(2).strip()
desc = match.group(3).strip()
if title and title not in ['', '[project name]']:
contributions.append({'title': title, 'url': url, 'description': desc})
if contributions:
data['contributions'] = contributions
# Extract gallery URLs
gallery_match = re.search(r'\*\*Photo Gallery\*\*.*?URL\(s\).*?:(.+?)(?=\n\*\*|$)', issue_body, re.IGNORECASE | re.DOTALL)
if gallery_match:
gallery_text = gallery_match.group(1)
# Find all URLs in the gallery section
url_pattern = r'https?://[^\s\)]+(?:\.jpg|\.jpeg|\.png|\.gif)?'
gallery_urls = re.findall(url_pattern, gallery_text, re.IGNORECASE)
if gallery_urls:
data['gallery_urls'] = gallery_urls
return data
def normalize_filename(self, name: str, handle: str = None) -> str:
"""
Convert a person's name to a normalized filename.
Args:
name: Person's full name
handle: Optional handle/nickname
Returns:
Normalized filename (lowercase, no spaces, no special chars)
"""
# Use handle if provided and seems better
if handle:
# Remove @ symbol if present
handle = handle.lstrip('@')
# If handle is simple (no spaces), prefer it
if ' ' not in handle:
base = handle
else:
base = name
else:
base = name
# Remove parenthetical nicknames
base = re.sub(r'\([^)]*\)', '', base).strip()
# Convert to lowercase
base = base.lower()
# Remove special characters, keep only alphanumeric
base = re.sub(r'[^a-z0-9]+', '', base)
return base
def extract_person_data(self, issue: Dict) -> Dict:
"""
Extract and structure person data from issue.
Args:
issue: GitHub issue dictionary
Returns:
Structured person data dictionary
"""
self.logger.info(f"Extracting data from issue #{issue['number']}: {issue['title']}")
# Parse the issue body
parsed_data = self.parse_issue_template(issue.get('body', ''))
# Also check comments for additional data
for comment in issue.get('comments', []):
comment_data = self.parse_issue_template(comment.get('body', ''))
# Merge comment data (don't overwrite existing)
for key, value in comment_data.items():
if key not in parsed_data:
parsed_data[key] = value
# Build person data structure
person = {
'issue_number': issue['number'],
'issue_url': issue['url'],
'firstname': parsed_data.get('firstname', ''),
'lastname': parsed_data.get('lastname', ''),
'handle': parsed_data.get('handle', ''),
'birth': parsed_data.get('birth', ''),
'death': parsed_data.get('death', ''),
'obituary': parsed_data.get('obituary', ''),
'affiliations': parsed_data.get('affiliations', ''),
'description': parsed_data.get('description', ''),
'mainimage_url': parsed_data.get('mainimage_url', ''),
'socialmedialinks': [],
'contributions': parsed_data.get('contributions', []),
'gallery_urls': parsed_data.get('gallery_urls', []),
}
# Build social media links
social_mapping = {
'Twitter': 'twitter',
'Github': 'github',
'LinkedIn': 'linkedin',
'Facebook': 'facebook',
'Wikipedia': 'wikipedia',
'Website': 'other_url',
}
for sitename, field in social_mapping.items():
url = parsed_data.get(field, '')
if url and url.startswith('http'):
person['socialmedialinks'].append({'sitename': sitename, 'siteurl': url})
# Generate display name
if person['firstname'] and person['lastname']:
displayname = f"{person['firstname']} {person['lastname']}"
elif person['firstname']:
displayname = person['firstname']
elif person['lastname']:
displayname = person['lastname']
elif person['handle']:
displayname = person['handle']
else:
# Fall back to issue title
displayname = issue['title']
# Add handle to display name if present
if person['handle'] and person['handle'] not in displayname:
displayname = f"{displayname} ({person['handle']})"
person['displayname'] = displayname
# Generate filename
name_for_file = f"{person['firstname']} {person['lastname']}".strip()
if not name_for_file:
name_for_file = person['handle'] or displayname
person['filename'] = self.normalize_filename(name_for_file, person['handle'])
return person
def generate_biography(self, person: Dict) -> str:
"""
Generate HTML biography from person data.
Args:
person: Person data dictionary
Returns:
HTML biography string
"""
bio = person.get('description', '')
if not bio:
# Generate placeholder bio
name = person.get('firstname', person.get('handle', 'This individual'))
affiliation = person.get('affiliations', '')
if affiliation:
bio = f"{name} was an information security professional and {affiliation} member."
else:
bio = f"{name} was an information security professional."
# Wrap in paragraph tags
if not bio.startswith('<p>'):
bio = f"<p>{bio}</p>"
return bio
def generate_memorial_json(self, person: Dict) -> Dict:
"""
Generate memorial JSON structure from person data.
Args:
person: Person data dictionary
Returns:
Complete memorial JSON dictionary
"""
self.logger.info(f"Generating memorial JSON for {person['displayname']}")
# Read template
template_path = self.repo_root / self.config['paths']['template']
with open(template_path, 'r') as f:
memorial = json.load(f)
# Populate fields
memorial['firstname'] = person['firstname']
memorial['lastname'] = person['lastname']
memorial['handle'] = person['handle']
memorial['birth'] = person['birth']
memorial['death'] = person['death']
memorial['obituary'] = person.get('obituary', '')
memorial['issue'] = str(person['issue_number'])
memorial['affiliations'] = person.get('affiliations', '')
memorial['maintext'] = self.generate_biography(person)
# Social media links (only non-empty)
memorial['socialmedialinks'] = [
link for link in person['socialmedialinks']
if link.get('siteurl')
]
# Contributions (only non-empty)
memorial['contributions'] = [
contrib for contrib in person.get('contributions', [])
if contrib.get('title')
]
# Main image - will be set during image processing
# For now, use default if no URL provided
if person.get('mainimage_url'):
memorial['mainimage'] = f"/images/{person['filename']}.jpg"
else:
memorial['mainimage'] = "/images/face-silhouette-clipart.png"
# Gallery - will be populated during image processing
memorial['gallery'] = []
return memorial
def save_memorial_json(self, person: Dict, memorial: Dict, dry_run: bool = False) -> bool:
"""
Save memorial JSON to file.
Args:
person: Person data dictionary
memorial: Memorial JSON dictionary
dry_run: If True, don't actually write file
Returns:
True if successful
"""
filename = person['filename']
json_path = self.repo_root / self.config['paths']['people_dir'] / f"{filename}.json"
if dry_run:
self.logger.info(f"[DRY RUN] Would save memorial JSON to: {json_path}")
self.logger.info(f"[DRY RUN] Content: {json.dumps(memorial, indent=2)}")
return True
try:
with open(json_path, 'w') as f:
json.dump(memorial, f, indent=2, ensure_ascii=False)
f.write('\n') # Ensure file ends with newline
self.logger.info(f"Saved memorial JSON to: {json_path}")
return True
except Exception as e:
self.logger.error(f"Failed to save memorial JSON: {e}")
return False
def prioritize_issues(self, issues: List[Dict]) -> List[Dict]:
"""
Sort issues by priority (high-profile people first).
Args:
issues: List of issue dictionaries
Returns:
Sorted list of issues
"""
high_profile = self.config['priorities']['high_profile']
def get_priority(issue):
title = issue['title']
# Check if any high-profile name is in the title
for idx, name in enumerate(high_profile):
if name.lower() in title.lower():
return idx # Lower number = higher priority
return 999 # Low priority
sorted_issues = sorted(issues, key=get_priority)
self.logger.info(f"Prioritized {len(sorted_issues)} issues")
for i, issue in enumerate(sorted_issues[:5]):
self.logger.info(f" Priority {i+1}: #{issue['number']} - {issue['title']}")
return sorted_issues
def process_issue(self, issue_number: int, dry_run: bool = False) -> bool:
"""
Process a single issue end-to-end.
Args:
issue_number: GitHub issue number
dry_run: If True, don't make any file changes
Returns:
True if successful
"""
self.logger.info(f"{'[DRY RUN] ' if dry_run else ''}Processing issue #{issue_number}")
# Fetch issue details
issue = self.fetch_issue_details(issue_number)
if not issue:
return False
# Extract person data
person = self.extract_person_data(issue)
# Validate minimum requirements
if not person['filename']:
self.logger.error(f"Cannot generate filename for issue #{issue_number}")
return False
if not person['death']:
self.logger.warning(f"No death year for issue #{issue_number}")
# Generate memorial JSON
memorial = self.generate_memorial_json(person)
# Save memorial JSON
success = self.save_memorial_json(person, memorial, dry_run=dry_run)
return success
def main():
"""Main entry point."""
parser = argparse.ArgumentParser(
description='Process RestInCode GitHub Issues to create memorials',
formatter_class=argparse.RawDescriptionHelpFormatter
)
parser.add_argument('--issue', type=int, help='Process specific issue number')
parser.add_argument('--dry-run', action='store_true', default=True,
help='Run without making any file changes (DEFAULT)')
parser.add_argument('--live', action='store_true',
help='Actually create files (disables dry-run)')
args = parser.parse_args()
# Determine if this is a dry run
dry_run = not args.live
processor = IssueProcessor()
# Show mode clearly
mode = "DRY RUN MODE - NO CHANGES WILL BE MADE" if dry_run else "LIVE MODE - WILL CREATE FILES"
processor.logger.info("=" * 60)
processor.logger.info(f"MODE: {mode}")
processor.logger.info("=" * 60)
if not dry_run:
processor.logger.warning("LIVE mode enabled - files will be created!")
response = input("Are you sure you want to continue? (yes/no): ")
if response.lower() != 'yes':
processor.logger.info("Aborted by user")
return 0
# Default to test issue if none specified
test_issue = args.issue or 197
processor.logger.info(f"Processing issue #{test_issue}")
success = processor.process_issue(test_issue, dry_run=dry_run)
if success:
processor.logger.info("Processing completed successfully")
else:
processor.logger.error("Processing failed")
return 1
return 0
if __name__ == '__main__':
sys.exit(main())

View file

@ -1,3 +0,0 @@
PyYAML>=6.0
Pillow>=10.0.0
requests>=2.31.0