I Created GoobyDesk
Howdy Internet! I am proud to say that I created GoobyDesk. Out of the box, GoobyDesk is a databaseless IT Service Desk written in Python3 using the Flask framework. It is rather lightweight and the code is easy to read. In this blog post, I’ll share some snippets of code and explain how and why I did certain operations. Some parts of this code were created using ChatGPTs generative code creation. I have no problems telling you I used Generative AI on this project.
I’ve always wanted to provide something to the open-source community. I use a list of open-source tools a mile long. However all the projects have complexity above my knowledge. I would be that guy looking to “fix” code comments right? So I never made any Pull Requests/Merge Requests. Now it’s December 2024 and the self-hosted IT Service Desk solution, Peppermint.sh, was short of official abondonded. The Developer “Potts” announced in his Discord he would be putting effort elsewhere and good luck. All is well, but I had two small issues…
Issue 1: When someone would submit a ticket, it would display a pop-up error to the user reading something along the lines of, “ticket creation failed.” The ticket would be succesfully saved into the SQLite database resulting in duplicate submissions.
Issue 2: Email reply tracking did not work at all.
So here we are!
Instead of an SQLite database; generally speaking, I am not a fan of databases. They add code complexity, vulnerabilities, and overall just a mess. I chose to read and write to a JSON document. I had learned to work with Python and JSON together by reading on W3Schools.
#def load_tickets():
# try:
# with open(TICKETS_FILE, "r") as tkt_file:
# return json.load(tkt_file)
# except FileNotFoundError:
# return [] # represents an empty list.
This was the first time I had ever worked with multi-threading and I learned a bunch about how python threads work.
def background_email_monitor():
while True:
fetch_email_replies()
time.sleep(300) # Wait for emails every 5 minutes.
threading.Thread(target=background_email_monitor, daemon=True).start()
The less flexible open
@app.route("/close_ticket/<ticket_number>", methods=["POST"])
def close_ticket(ticket_number):
if not session.get("technician"): # Check the cookie for technician tag.
return render_template("403.html"), 403
tickets = load_tickets()
for ticket in tickets:
if ticket["ticket_number"] == ticket_number: # Basic input validation.
ticket["ticket_status"] = "Closed"
save_tickets(tickets)
send_TktClosed_discord_notification(ticket_number) # Discord notification for closing a ticket.
return jsonify({"message": f"Ticket {ticket_number} has been closed."}) # Browser Popup to confirm ticket closure.
# If the ticket was not found....
return render_template("404.html"), 404
The better version
@app.route("/ticket/<ticket_number>/update_status/<ticket_status>", methods=["POST"])
def update_ticket_status(ticket_number, ticket_status):
if not session.get("technician"): # Ensure only authenticated techs can update tickets.
return render_template("403.html"), 403 # Otherwise, custom 403 error.
valid_statuses = ["Open", "In-Progress", "Closed"]
if ticket_status not in valid_statuses:
return render_template("400.html"), 400 # Return HTTP 400 but this may change.
tickets = load_tickets() # Loads tickets into memory.
for ticket in tickets:
if ticket["ticket_number"] == ticket_number:
ticket["ticket_status"] = ticket_status
save_tickets(tickets) # Save the changes to the tickets.
send_TktClosed_discord_notification(ticket_number, ticket_status) # Discord notification for closing a ticket.
return jsonify({"message": f"Ticket {ticket_number} updated to {ticket_status}."}) # Browser prompt on successful status update.
return render_template("404.html"), 404
Exploring Greece, In the southern Balkan Peninsula.
How-To Import a custom world into Singleplayer, then Realms using Minecraft Bedrock Edition.
Remeber Alex
Remebering Alondra and Aaliyah
Matt’s Guide to ADS-B
Matt’s Guide to FRS and GRMS Radio
Matt’s Guide to CB Radio
Matt’s Guide to Securing a Linux Box for Production.
My Experience deploying NextCloud AIO Docker Image
Quick overview of my websites architecture.
One Night in Glacier NP - 2024
Exploring and capturing the scenery in American Truck Simulator, Nebraska DLC
how-to be safe while downloading linux isos.
Exploring South Dakota with the Jacksons.
how I reduced my home page 610 percent.
how-to add oneko.js to the minimal-mistakes jekyll template.
My personal running notes for growing cannabis.
Dealing with CIFS errors between TrueNAS and Debian.
how-to bounce a Juniper JunOS switchport.
how-to fix ‘the list of sources could not be read.’ when using apt.
how-to troubleshoot a home network, by a Network Engineer.
Moving my webserver from OpenLiteSpeed to Caddy
how-to resolve, could not resolve packages.adoptium.net
how-to validate XZ-Utils impact.
How and Why I use Ninite
Manually renewing Certbot on OpenLiteSpeed
Yet Another Benchmark Results
Linux Basics and Core Concepts by Matt F.
how-to Buy and Manage a Web Domain
My Udemy Course Completion Certification.
Scion FRS Service Manual Download and Sources
My Discord Server Widget
How I moved from QUIC.Cloud to BunnyNet CDN.
My High Uptime Plan for 2024.
Personal notes for Magic the Gathering
HTML Hobbiest Webring Landing Page/Post
Method of Procedure for migrating from WordPress to plain HTML.
W900 Tuning Pack DLC Review.
Google Domains is Ending.
Deep dive into OpenLiteSpeed webserver.
how-to resolve my Jekyll/Cloudflare Pages deployment error.
In High School I had one dream that stands out. Own a Porsche by the time I was 26. Looking back, I have no idea where this dream came from; because I was ra...
Personal ramblings about my new town.
Knowledge Filled PDF Bundle
how-to Jellyfun.
ProtonMail Review - 1 Year
how-to manage Pi-Hole.
My new Gaming PC. Its boring but it’ll do.
how-to setup Pi-Hole and Wireguard on Linode.
how-to update the hostname of a Raspberry Pi.
Can a Raspberry Pi Zero host a family VPN Server? Yes.
Logitech G413 Keyboard review.
Razer Huntsman Mini review.
YouTube video cruising through Colorado!
Ramblings about PiAware after one month of operation.
Guide to setup a Raspberry Pi from start to finish!
Guide to configuring the Timezone on a Raspberry Pi.