- #! /usr/bin/python3
-
- from app import app, db
- from app.models.users import Member, Group, GroupPrivilege
- from app.models.privs import SpecialPrivilege
- from app.models.trophies import Trophy, Title, TrophyMember
- from app.models.forum import Forum
- from app.utils import unicode_names
- import os
- import sys
- import yaml
- import readline
- import slugify
- from PIL import Image
-
- help_msg = """
- This is the Planète Casio master shell. Type 'exit' or C-D to leave.
-
- Type a category name to see a list of elements. Available categories are:
-
- 'members' Registered community members
- 'groups' Privilege groups
- 'trophies' Trophies
- 'trophy-members' Trophies owned by members
- 'forums' Forum tree
-
- Type a category name followed by 'clear' to remove all entries in the category.
-
- Type 'create-groups-and-privs' to recreate all groups and privileges to the
- default. This function generates a minimal set of groups and members to prepare
- the database.
- 1. Deletes all groups
- 2. Creates groups 'Administrateur', 'Modérateur', 'Développeur', 'Rédacteur',
- 'Responsable Communauté', 'Partenaire', 'Compte communautaire', 'Robot', and
- 'Membre de CreativeCalc'
- 3. Grants privileges related to these groups
- 4. Recreates common accounts: 'Planète Casio' (community account) and 'GLaDOS'
- (robot)
-
- Type 'add-group <member> #<group-id>' to add a new member to a group.
-
- Type 'create-trophies' to reset trophies and titles and their icons.
-
- Type 'create-forums' to reset the forum tree.
- """
-
- #
- # Category viewers
- #
-
- def members(*args):
- if args == ("clear",):
- for m in Member.query.all():
- m.delete()
- db.session.commit()
- print("Removed all members.")
- return
-
- for m in Member.query.all():
- print(m)
-
- def groups(*args):
- if args == ("clear",):
- for g in Group.query.all():
- g.delete()
- db.session.commit()
- print("Removed all groups.")
- return
-
- for g in Group.query.all():
- print(f"#{g.id} {g.name}")
-
- def trophies(*args):
- if args == ("clear",):
- for t in Trophy.query.all():
- db.session.delete(t)
- db.session.commit()
- print("Removed all trophies.")
- return
-
- for t in Trophy.query.all():
- print(t)
-
- def trophy_members(*args):
- for t in Trophy.query.all():
- if t.owners == []:
- continue
-
- print(t)
- for m in t.owners:
- print(f" {m}")
-
- def forums(*args):
- if args == ("clear",):
- for f in Forum.query.all():
- db.session.delete(f)
- db.session.commit()
- print("Removed all forums.")
- return
-
- for f in Forum.query.all():
- parent = f"in {f.parent.url}" if f.parent is not None else "root"
- print(f"{f.url} ({parent}) [{f.prefix}]: {f.name}")
- print(f" {f.descr}")
-
- #
- # Creation and edition
- #
-
- def create_groups_and_privs():
- # Clean up groups
- groups("clear")
-
- # Create base groups
- gr = []
- with open(os.path.join(app.root_path, "data", "groups.yaml")) as fp:
- gr = yaml.safe_load(fp.read())
-
- for g in gr:
- g["obj"] = Group(g["name"], g["css"], g["descr"])
- db.session.add(g["obj"])
- db.session.commit()
-
- for g in gr:
- for priv in g.get("privs", "").split():
- db.session.add(GroupPrivilege(g["obj"], priv))
- db.session.commit()
-
- print(f"Created {len(gr)} groups.")
-
- # Clean up test members
- for name in "PlanèteCasio GLaDOS".split():
- m = Member.query.filter_by(name=name).first()
- if m is not None:
- m.delete()
-
- print("Removed test members.")
-
- # Create template members
-
- def addgroup(member, group):
- g = Group.query.filter_by(name=group).first()
- if g is not None:
- member.groups.append(g)
-
- m = Member("PlanèteCasio", "contact@planet-casio.com", "nologin")
- addgroup(m, "Compte communautaire")
- addgroup(m, "No login")
- db.session.add(m)
-
- m = Member("GLaDOS", "glados@aperture.science", "nologin")
- m.xp = 1338
- addgroup(m, "Robot")
- addgroup(m, "No login")
- db.session.add(m)
- db.session.commit()
-
- db.session.add(SpecialPrivilege(m, "edit-posts"))
- db.session.add(SpecialPrivilege(m, "shoutbox-ban"))
-
- db.session.commit()
-
- print(f"Created 2 test members with some privileges.")
-
-
- def create_trophies():
- # Clean up trophies
- trophies("clear")
-
- # Create base trophies
- tr = []
- with open(os.path.join(app.root_path, "data", "trophies.yaml")) as fp:
- tr = yaml.safe_load(fp.read())
-
- for t in tr:
- description = t.get("description", "")
-
- if t["is_title"]:
- trophy = Title(t["name"], description, t["hidden"],
- t.get("css", ""))
- else:
- trophy = Trophy(t["name"], description, t["hidden"])
- db.session.add(trophy)
- db.session.commit()
-
- print(f"Created {len(tr)} trophies.")
-
- # Create their icons in /app/static/images/trophies
- names = [ slugify.slugify(t["name"]) for t in tr ]
- src = os.path.join(app.root_path, "data", "trophies.png")
- dst = os.path.join(app.root_path, "static", "images", "trophies")
-
- try:
- os.mkdir(dst)
- except FileExistsError:
- pass
-
- img = Image.open(src)
-
- def trophy_iterator(img):
- for y in range(img.height // 26):
- for x in range(img.width // 26):
- icon = img.crop((26*x+1, 26*y+1, 26*x+25, 26*y+25))
- # Skip blank squares in the source image
- if len(icon.getcolors()) > 1:
- yield icon.resize((48,48))
-
- for (name, icon) in zip(names, trophy_iterator(img)):
- icon.save(os.path.join(dst, f"{name}.png"))
-
- def create_forums():
- # Clean up forums
- forums("clear")
-
- # Create the forum tree
- fr = []
- success = 0
- with open(os.path.join(app.root_path, "data", "forums.yaml")) as fp:
- fr = yaml.safe_load(fp.read())
-
- for url, f in fr.items():
- if url == "/":
- parent = None
- else:
- parent_url = url.rsplit('/', 1)[0]
- if parent_url == "":
- parent_url = "/"
- parent = Forum.query.filter_by(url=parent_url).first()
-
- if parent is None:
- print(f"error: no parent with url {parent_url} for {url}")
- continue
-
- f = Forum(url, f['name'], f['prefix'], f.get('descr', ''), parent)
- db.session.add(f)
- success += 1
-
- db.session.commit()
- print(f"Created {success} forums.")
-
- def add_group(member, group):
- if group[0] != "#":
- print(f"error: group id {group} should start with '#'")
- return
- gid = int(group[1:])
-
- norm = unicode_names.normalize(member)
-
- g = Group.query.filter_by(id=gid).first()
- m = Member.query.filter_by(norm=norm).first()
-
- if m is None:
- print(f"error: no member has a normalized name of '{norm}'")
- return
-
- m.groups.append(g)
- db.session.add(m)
- db.session.commit()
-
- #
- # Main program
- #
-
- print(help_msg)
-
- commands = {
- "exit": lambda: sys.exit(0),
- "members": members,
- "groups": groups,
- "trophies": trophies,
- "trophy-members": trophy_members,
- "forums": forums,
- "create-groups-and-privs": create_groups_and_privs,
- "create-trophies": create_trophies,
- "create-forums": create_forums,
- "add-group": add_group,
- }
-
- while True:
- try:
- print("@> ", end="")
- cmd = input().split()
- except EOFError:
- sys.exit(0)
-
- if not cmd:
- continue
- if cmd[0] not in commands:
- print(f"error: unknown command '{cmd[0]}'")
- else:
- commands[cmd[0]](*cmd[1:])
|