Add initial idlerpg script. - annna - Annna the nice friendly bot.
 (HTM) git clone git://bitreich.org/annna/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/annna/
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Tags
 (DIR) README
       ---
 (DIR) commit 033db9ba505d80e24fa0f8ae17ec0410dfa9ccd4
 (DIR) parent a21e6cfb498b88e53eb1c8ca41b7749903f2e010
 (HTM) Author: Annna Robert-Houdin <annna@bitreich.org>
       Date:   Sun, 27 Aug 2023 13:06:33 +0200
       
       Add initial idlerpg script.
       
       Diffstat:
         A modules/idlerpg/.idlerpg-channel-s… |       0 
         A modules/idlerpg/admins.txt          |       1 +
         A modules/idlerpg/classes.txt         |      34 +++++++++++++++++++++++++++++++
         A modules/idlerpg/hackers.txt         |       4 ++++
         A modules/idlerpg/hardware.txt        |      29 +++++++++++++++++++++++++++++
         A modules/idlerpg/idlerpg-channel-se… |     257 +++++++++++++++++++++++++++++++
         A modules/idlerpg/penalties.txt       |       6 ++++++
         A modules/idlerpg/shields.txt         |      11 +++++++++++
         A modules/idlerpg/weapons.txt         |      15 +++++++++++++++
       
       9 files changed, 357 insertions(+), 0 deletions(-)
       ---
 (DIR) diff --git a/modules/idlerpg/.idlerpg-channel-service.py.swp b/modules/idlerpg/.idlerpg-channel-service.py.swp
       Binary files differ.
 (DIR) diff --git a/modules/idlerpg/admins.txt b/modules/idlerpg/admins.txt
       @@ -0,0 +1 @@
       +__20h__
 (DIR) diff --git a/modules/idlerpg/classes.txt b/modules/idlerpg/classes.txt
       @@ -0,0 +1,34 @@
       +pirate
       +hacker
       +lurker
       +leecher
       +bitreich_member
       +c_programmer
       +c++_programmer
       +vala_programmer
       +lua_programmer
       +visual_basic_programmer
       +cobol_programmer
       +rust_programmer
       +php_programmer
       +javascript_programmer
       +backend_programmer
       +frontend_programmer
       +logo_programmer
       +excel_user
       +gopher_user
       +gopher_designer
       +web_user
       +web_designer
       +gentoo_developer
       +gentoo_user
       +linux_developer
       +linux_user
       +openbsd_developer
       +openbsd_user
       +netbsd_developer
       +netbsd_user
       +freebsd_developer
       +freebsd_user
       +windows_developer
       +windows_user
 (DIR) diff --git a/modules/idlerpg/hackers.txt b/modules/idlerpg/hackers.txt
       @@ -0,0 +1,4 @@
       +__20h__        475        logo_programmer        pinebook        snakeoil        oscilloscope        0
       +\subline        1375        web_user        purism_librem_15        cloud_security        oscilloscope        0
       +kroovy        1375        netbsd_developer        system76_oryx        chroot        ed(1)        0
       +adc        775        windows_developer        thinkpad_T_laptop        laughable_programming_style        mouse        0
 (DIR) diff --git a/modules/idlerpg/hardware.txt b/modules/idlerpg/hardware.txt
       @@ -0,0 +1,29 @@
       +system76_gazelle
       +system76_adder
       +system76_oryx
       +system76_serval
       +system76_bonobo
       +system76_galago
       +system76_lemur
       +system76_darter
       +system76_pangolin
       +thinkpad_T_laptop
       +thinkpad_R_laptop
       +thinkpad_X_laptop
       +thinkpad_A_laptop
       +thinkpad_S_laptop
       +thinkpad_G_laptop
       +thinkpad_Z_laptop
       +pinebook
       +pinebook_pro
       +pinephone
       +pinephone_pro
       +framework_13
       +framework_16
       +chromebook
       +android_phone
       +iphone
       +fairphone
       +purism_librem_13
       +purism_librem_14
       +purism_librem_15
 (DIR) diff --git a/modules/idlerpg/idlerpg-channel-service.py b/modules/idlerpg/idlerpg-channel-service.py
       @@ -0,0 +1,257 @@
       +#!/usr/bin/env python
       +# coding=UTF-8
       +#
       +# Copy me, if you can.
       +# by 20h
       +#
       +
       +import os
       +import sys
       +import getopt
       +import time
       +import random
       +import select
       +import pyinotify
       +import errno
       +import fcntl
       +import functools
       +
       +def readin_file(f):
       +    lines = []
       +    try:
       +        fd = open(f)
       +    except:
       +        sys.exit(1)
       +    lines = [e.strip() for e in fd.readlines()]
       +    fd.close()
       +    return lines
       +
       +def readin_dictfile(f):
       +    lines = []
       +    rdict = {}
       +    try:
       +        fd = open(f)
       +    except:
       +        sys.exit(1)
       +    lines = [e.strip().split("\t") for e in fd.readlines()]
       +    fd.close()
       +    for line in lines:
       +        rdict[line[0]] = line[1:]
       +    return rdict
       +
       +def writeout_dictfile(f, d):
       +    try:
       +        fd = open(f, "w")
       +    except:
       +        sys.exit(1)
       +    for key in d.keys():
       +        fd.write("%s\t%s\n" % (key, "\t".join([str(s) for s in d[key]])))
       +    fd.flush()
       +    fd.close()
       +
       +def say(fpath, text):
       +    fd = open(fpath, "w")
       +    print("%s -> say: %s" % (fpath, text))
       +    fd.write("%s\n" % (text))  
       +    fd.flush()
       +    fd.close()
       +
       +def usage(app):
       +    app = os.path.basename(app)
       +    print("usage: %s [-h] ircuser basepath ircpath server channel" % (app), file=sys.stderr)
       +    sys.exit(1)
       +
       +def main(args):
       +    try:
       +        opts, largs = getopt.getopt(args[1:], "h")
       +    except getopt.GetoptError as err:
       +        print(str(err))
       +        usage(args[0])
       +
       +    for o, a in opts:
       +        if opts == "-h":
       +            usage(args[0])
       +        else:
       +            assert False, "unhandled option"
       +
       +    if len(largs) < 5:
       +        usage(args[0])
       +        return 1
       +
       +    ircuser = largs[0]
       +    basepath = largs[1]
       +    ircpath = largs[2]
       +    server = largs[3]
       +    channel = largs[4]
       +    serverpath = "%s/%s" % (ircpath, server)
       +    print("serverpath = %s" % (serverpath))
       +    chanpath = "%s/%s" % (serverpath, channel)
       +    print("chanpath = %s" % (chanpath))
       +
       +    chaninpath = "%s/in" % (chanpath)
       +    say(chaninpath, "/names %s\n" % (channel))
       +
       +    serveroutlines = readin_file("%s/out" % (serverpath))
       +    namesstring = " 353 %s = %s :" % (ircuser, channel)
       +    users = []
       +    for line in serveroutlines[::-1]:
       +        if namesstring in line:
       +            for user in line.strip().split(namesstring)[1].split(" "):
       +                if user.startswith("@"):
       +                    user = user[1:]
       +                if user not in users:
       +                    users.append(user)
       +    print("users = %s" % (users))
       +    if len(users) == 0:
       +        return 1
       +
       +    penalties = readin_dictfile("%s/penalties.txt" % (basepath))
       +    print(penalties)
       +
       +    classes = readin_dictfile("%s/classes.txt" % (basepath))
       +    print(classes)
       +    hardware = readin_dictfile("%s/hardware.txt" % (basepath))
       +    print(hardware)
       +    shields = readin_dictfile("%s/shields.txt" % (basepath))
       +    print(shields)
       +    weapons = readin_dictfile("%s/weapons.txt" % (basepath))
       +    print(weapons)
       +
       +    hackers = readin_dictfile("%s/hackers.txt" % (basepath))
       +    for hacker in hackers.keys():
       +        hackers[hacker][0] = int(hackers[hacker][0])
       +        hackers[hacker][5] = int(hackers[hacker][5])
       +    print(hackers)
       +    admins = readin_dictfile("%s/admins.txt" % (basepath))
       +    print(admins)
       +
       +    def random_hacker():
       +        hacker = []
       +        # Idletime
       +        hacker.append(0)
       +        # Class
       +        hacker.append(random.choice(list(classes.keys())))
       +        # Hardware
       +        hacker.append(random.choice(list(hardware.keys())))
       +        # Shield
       +        hacker.append(random.choice(list(shields.keys())))
       +        # Weapon
       +        hacker.append(random.choice(list(weapons.keys())))
       +        # Level
       +        hacker.append(0)
       +        return hacker
       +
       +    def hacker_info(hackers, hacker):
       +        hackerinfo =  "The hacker %s of the class %s " % (hacker, hackers[hacker][1])
       +        hackerinfo += "is using his %s hardware " % (hackers[hacker][2])
       +        hackerinfo += "which is protected by %s. " % (hackers[hacker][3])
       +        hackerinfo += "%s's weapon is %s. " % (hacker, hackers[hacker][4])
       +        hackerinfo += "%s has idled for %d seconds and has reached level %d." % (hacker, hackers[hacker][0], hackers[hacker][5])
       +        say(chaninpath, hackerinfo)
       +
       +    for user in users:
       +        if user not in list(hackers.keys()) and user != ircuser:
       +            hackers[user] = random_hacker()
       +    print(hackers)
       +
       +    inotifywm = pyinotify.WatchManager()
       +    inotifywm.add_watch("%s/out" % (chanpath), pyinotify.IN_MODIFY)
       +    inotifyfd = inotifywm.get_fd()
       +
       +    def event_processor(notifier):
       +        pass
       +    notifier = pyinotify.Notifier(inotifywm, default_proc_fun=event_processor)
       +
       +    chanoutfd = open("%s/out" % (chanpath), "r+")
       +    chanoutfd.readlines()
       +    while 1:
       +        # Game ticks every 5 seconds.
       +        try:
       +            (rfds, wfds, sfds) = select.select([inotifyfd], [], [], 5)
       +        except select.error as err:
       +            if err.args[0] == errno.EINTR:
       +                continue
       +            break
       +        if rfds == [] and wfds == [] and sfds == []:
       +            print("game tick")
       +            for hacker in hackers.keys():
       +                hackers[hacker][0] += 5
       +                # Level up every 5 days.
       +                newlevel = int(hackers[hacker][0]/(86400*5))
       +                if newlevel > hackers[hacker][5]:
       +                    say(chaninpath, "%s levelled up to level %s!" % (hacker, newlevel))
       +                elif newlevel < hackers[hacker][5]:
       +                    say(chaninpath, "%s levelled down to level %s." % (hacker, newlevel))
       +                hackers[hacker][5] = newlevel
       +            writeout_dictfile("%s/hackers.txt" % (basepath), hackers)
       +            continue
       +   
       +        notifier.read_events()
       +        notifier.process_events()
       +
       +        lines = chanoutfd.readlines()
       +        lines = [line.strip() for line in lines]
       +        for line in lines:
       +            if line == None or line == "":
       +                continue
       +            print("line = '%s'" % (line))
       +
       +            penalty = None
       +            try:
       +                (timestamp, user, remain) = line.split(" ", 2)
       +            except ValueError:
       +                continue
       +
       +            if user.startswith("<") and user.endswith(">"):
       +                hacker = user.split("<", 1)[1].split(">", 1)[0]
       +                if hacker in admins.keys():
       +                    print("is admin")
       +                    if remain.startswith("!"):
       +                        (cmd, *cmdargs) = remain.split(" ")
       +                        print("cmd = %s; cmdargs = %s" % (cmd, cmdargs))
       +                        if cmd == "!info":
       +                            if len(cmdargs) > 0:
       +                                if cmdargs[0] in hackers:
       +                                    hacker_info(hackers, cmdargs[0])
       +                            else:
       +                                hacker_info(hackers, hacker)
       +                else:
       +                    penalty = "text"
       +
       +            elif user == "-!-":
       +                (hacker, text) = remain.split(" ", 1)
       +                if "has joined " in text:
       +                    penalty = "join"
       +                    hacker = hacker.split("(", 1)[0]
       +                    if hacker not in hackers:
       +                        hackers[hacker] = random_hacker()
       +                        hacker_info(hackers, hacker)
       +                elif "has left " in text:
       +                    penalty = "part"
       +                    hacker = hacker.split("(", 1)[0]
       +                elif "has quit " in text:
       +                    penalty = "quit"
       +                    hacker = hacker.split("(", 1)[0]
       +                elif "changed nick to " in text:
       +                    penalty = "nick"
       +                elif "kicked " in text:
       +                    penalty = "kick"
       +                    hacker = text.split(" ", 3)[2]
       +
       +            if hacker == ircuser:
       +                continue
       +            if hacker not in hackers:
       +                continue
       +
       +            if penalty != None and penalty in penalties:
       +                penaltytime = int(penalties[penalty][0])
       +                hackers[hacker][0] -= penaltytime
       +                say(chaninpath, "%s, your idletime has been reduced by %d to %d due to the %s penalty." \
       +                        % (hacker, penaltytime, hackers[hacker][0], penalty))
       +                writeout_dictfile("%s/hackers.txt" % (basepath), hackers)
       +    
       +    return 0
       +
       +if __name__ == "__main__":
       +    sys.exit(main(sys.argv))
       +
 (DIR) diff --git a/modules/idlerpg/penalties.txt b/modules/idlerpg/penalties.txt
       @@ -0,0 +1,6 @@
       +text        300
       +quit        200
       +part        400
       +nick        250
       +kick        350
       +join        100
 (DIR) diff --git a/modules/idlerpg/shields.txt b/modules/idlerpg/shields.txt
       @@ -0,0 +1,11 @@
       +apparmor
       +unix_permissions
       +return_value_check
       +hardened_patches
       +chroot
       +pledge
       +snakeoil
       +laughable_programming_style
       +cloud_security
       +xml_firewall
       +air_gap
 (DIR) diff --git a/modules/idlerpg/weapons.txt b/modules/idlerpg/weapons.txt
       @@ -0,0 +1,15 @@
       +vt100
       +nmap(1)
       +web_browser
       +annna
       +chatgpt
       +keyboard
       +mouse
       +trackball
       +ethernet_cable
       +wifi_fryer
       +ir_diode
       +soldering_iron
       +oscilloscope
       +ed(1)
       +blockchain