• 2 Posts
  • 55 Comments
Joined 1 year ago
cake
Cake day: June 10th, 2023

help-circle



  • I code both typescript and python professionally, and python is almost as much of a mess, just a different kind of mess. The package manager ecosystem is all over the place, nobody is agreeing on a build system, and the type system is still unable to represent fairly simple concepts when it comes to function typing. Also tons of libraries just ignore types altogether. I love it, but as a competitor to JavaScript in the messiness department it’s not a good horse.





  • If you look at the repo, the very first line in the readme links to an issue that briefly explains why you should care.

    Unmaintained software comes in two categories:

    1. The software is done. It does exactly what it was meant to do and it was written in a language and in such a way as to be pretty future proof. Examples are some basic code libraries or command line utilities.
    2. The software had to be updated all the time to keep up with changing environments and security problems, so the dev got sick of it and dropped it. Or a better solution came along so the developer felt free to finally drop the burden.

    Nativefier falls in the second category and the second clause. Don’t use it.




  • You asked for my python script but now I can’t seem to load that comment to reply directly to it. Anyway, here’s the script, I haven’t bothered to upload the repo anywhere. I’m sure it isn’t perfect but it works fine for me. The action for opening evolution when you click the tray icon is specific to hyprland so will probably need to be modified to suit your needs.

    import asyncio
    import concurrent.futures
    import logging
    import signal
    import sqlite3
    import sys
    from pathlib import Path
    from subprocess import run
    
    import pkg_resources
    from inotify_simple import INotify, flags
    from PySimpleGUIQt import SystemTray
    
    menu_def = ["BLANK", ["Exit"]]
    
    empty_icon = pkg_resources.resource_filename(
        "evolution_tray", "resources/inbox-empty.svg"
    )
    full_icon = pkg_resources.resource_filename(
        "evolution_tray", "resources/inbox-full.svg"
    )
    
    inotify = INotify()
    
    tray = SystemTray(filename=empty_icon, menu=menu_def, tooltip="Inbox empty")
    
    logging.getLogger("asyncio").setLevel(logging.WARNING)
    handler = logging.StreamHandler(sys.stdout)
    logger = logging.getLogger()
    logger.setLevel("DEBUG")
    logger.addHandler(handler)
    
    
    def handle_menu_events():
        while True:
            menu_item = tray.read()
            if menu_item == "Exit":
                signal.raise_signal(signal.SIGTERM)
            elif menu_item == "__ACTIVATED__":
                run(["hyprctl", "dispatch", "exec", "evolution"])
                # tray.update(filename=paused_icon)
    
            logger.info("Opened evolution")
    
    
    def get_all_databases():
        cache_path = Path.home() / ".cache" / "evolution" / "mail"
        return list(cache_path.glob("**/folders.db"))
    
    
    def check_unread() -> int:
        unread = 0
        for db in get_all_databases():
            conn = sqlite3.connect(db)
            cursor = conn.cursor()
            try:
                cursor.execute("select count(*) read from INBOX where read == 0")
                unread += cursor.fetchone()[0]
            except:
                pass
            finally:
                conn.close()
    
        if unread > 0:
            tray.update(filename=full_icon, tooltip=f"{unread} unread emails")
        else:
            tray.update(filename=empty_icon, tooltip="Inbox empty")
    
        return unread
    
    
    def watch_inbox():
        while True:
            for database in get_all_databases():
                inotify.add_watch(database, mask=flags.MODIFY)
            while inotify.read():
                logger.info("New mail")
                logger.info(f"{check_unread()} new emails")
    
    
    async def main():
        executor = concurrent.futures.ThreadPoolExecutor(max_workers=1)
        loop = asyncio.get_running_loop()
        check_unread()
    
        watch_task = asyncio.wait(
            fs={
                loop.run_in_executor(executor, watch_inbox),
            },
            return_when=asyncio.FIRST_COMPLETED,
        )
        await asyncio.gather(watch_task, loop.create_task(handle_menu_events()))
    
    
    def entrypoint():
        signal.signal(signal.SIGINT, signal.SIG_DFL)
        signal.signal(signal.SIGTERM, signal.SIG_DFL)
    
        try:
            asyncio.run(main())
        except Exception as e:
            logger.exception(e)
    
    
    if __name__ == "__main__":
        entrypoint()
    

  • bjornsno@lemm.eetoSelfhosted@lemmy.worldMonitoring Borg backups
    link
    fedilink
    English
    arrow-up
    5
    ·
    edit-2
    5 months ago

    If you want to do this, what you probably want is to pump your logs into a log drain, something like betterstack is good. They then allow you to set up discrepancy thresholds and can send you emails when something seems to be out of the ordinary. There’s probably a self hosted thing that works the same way but I’ve never found a simple setup. You can do the whole Prometheus, influxdb, grafana setup but imo it’s too much work, and then you still have to set up email smtp separate from that.




  • bjornsno@lemm.eetoAsklemmy@lemmy.mlWhen is it "enough" money?
    link
    fedilink
    arrow-up
    8
    arrow-down
    3
    ·
    5 months ago

    Oooh look at Epicure over here, just casually getting in his 8 hours of sleep. Brag more king.

    On a serious note, the capitalists have commercialized all of this. Getting enough to eat might be doable with a meager income technically, but eating well and healthy is expensive. Getting a good bed in a nice living space that facilitates rest well costs a fortune. So you need two middle class plus jobs to afford it for yourself and your partner, which comes with its own set of stressors.

    The small things in life are also actively commercialized. A coffee with friends? Better save up for the chain cafe prices. A movie night in? Remember to pay your Netflix subscription. A hike? Gotta pay for gas to get there, depending on where you live. I’m not saying it’s impossible to have small things for free/cheap, it’s just not that easy. There’s also going to be constant social pressure, through advertisement or influencers, first or secondhand, to do all the things they tell you will make you more happy. You’ll have to actively resist that, which in turn can cause you to become distanced from your social circle.

    God forbid you get sick, the health insurance and pharmaceutical industry will fleece you and in some countries leave you with crippling debt, making all of the above out of reach for you.

    All of this to say: money isn’t just something you have to chase after for the sake of it in our current society, it’s an absolute necessity to try to have more than what you think you actually need in the moment to get by and enjoy the small things. It might sound cliche, but “society is like stacked against us, man” is actually a completely true statement.







  • bjornsno@lemm.eeOPtoSelfhosted@lemmy.worldHelp with deployment
    link
    fedilink
    English
    arrow-up
    1
    ·
    5 months ago

    That would fill the same role as watchtower I guess? I’ve previously tried to have a look at having portainer manage the docker compose stack that it’s running inside but at least back then it seemed to be a dead end and not really what portainer is meant to do. I’m not interested in moving away from docker compose at this time.