La version 5 de Planète Casio. Regroupe le forum, les programmes, les tutoriel, les sprites et tous les autres outils développés par nos soins.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

292 line
7.7 KiB

  1. #! /usr/bin/python3
  2. from app import app, db
  3. from app.models.users import Member, Group, GroupPrivilege
  4. from app.models.privs import SpecialPrivilege
  5. from app.models.trophies import Trophy, Title, TrophyMember
  6. from app.models.forum import Forum
  7. from app.utils import unicode_names
  8. import os
  9. import sys
  10. import yaml
  11. import readline
  12. import slugify
  13. from PIL import Image
  14. help_msg = """
  15. This is the Planète Casio master shell. Type 'exit' or C-D to leave.
  16. Type a category name to see a list of elements. Available categories are:
  17. 'members' Registered community members
  18. 'groups' Privilege groups
  19. 'trophies' Trophies
  20. 'trophy-members' Trophies owned by members
  21. 'forums' Forum tree
  22. Type a category name followed by 'clear' to remove all entries in the category.
  23. Type 'create-groups-and-privs' to recreate all groups and privileges to the
  24. default. This function generates a minimal set of groups and members to prepare
  25. the database.
  26. 1. Deletes all groups
  27. 2. Creates groups 'Administrateur', 'Modérateur', 'Développeur', 'Rédacteur',
  28. 'Responsable Communauté', 'Partenaire', 'Compte communautaire', 'Robot', and
  29. 'Membre de CreativeCalc'
  30. 3. Grants privileges related to these groups
  31. 4. Recreates common accounts: 'Planète Casio' (community account) and 'GLaDOS'
  32. (robot)
  33. Type 'add-group <member> #<group-id>' to add a new member to a group.
  34. Type 'create-trophies' to reset trophies and titles and their icons.
  35. Type 'create-forums' to reset the forum tree.
  36. """
  37. #
  38. # Category viewers
  39. #
  40. def members(*args):
  41. if args == ("clear",):
  42. for m in Member.query.all():
  43. m.delete()
  44. db.session.commit()
  45. print("Removed all members.")
  46. return
  47. for m in Member.query.all():
  48. print(m)
  49. def groups(*args):
  50. if args == ("clear",):
  51. for g in Group.query.all():
  52. g.delete()
  53. db.session.commit()
  54. print("Removed all groups.")
  55. return
  56. for g in Group.query.all():
  57. print(f"#{g.id} {g.name}")
  58. def trophies(*args):
  59. if args == ("clear",):
  60. for t in Trophy.query.all():
  61. db.session.delete(t)
  62. db.session.commit()
  63. print("Removed all trophies.")
  64. return
  65. for t in Trophy.query.all():
  66. print(t)
  67. def trophy_members(*args):
  68. for t in Trophy.query.all():
  69. if t.owners == []:
  70. continue
  71. print(t)
  72. for m in t.owners:
  73. print(f" {m}")
  74. def forums(*args):
  75. if args == ("clear",):
  76. for f in Forum.query.all():
  77. db.session.delete(f)
  78. db.session.commit()
  79. print("Removed all forums.")
  80. return
  81. for f in Forum.query.all():
  82. parent = f"in {f.parent.url}" if f.parent is not None else "root"
  83. print(f"{f.url} ({parent}) [{f.prefix}]: {f.name}")
  84. print(f" {f.descr}")
  85. #
  86. # Creation and edition
  87. #
  88. def create_groups_and_privs():
  89. # Clean up groups
  90. groups("clear")
  91. # Create base groups
  92. gr = []
  93. with open(os.path.join(app.root_path, "data", "groups.yaml")) as fp:
  94. gr = yaml.safe_load(fp.read())
  95. for g in gr:
  96. g["obj"] = Group(g["name"], g["css"], g["descr"])
  97. db.session.add(g["obj"])
  98. db.session.commit()
  99. for g in gr:
  100. for priv in g.get("privs", "").split():
  101. db.session.add(GroupPrivilege(g["obj"], priv))
  102. db.session.commit()
  103. print(f"Created {len(gr)} groups.")
  104. # Clean up test members
  105. for name in "PlanèteCasio GLaDOS".split():
  106. m = Member.query.filter_by(name=name).first()
  107. if m is not None:
  108. m.delete()
  109. print("Removed test members.")
  110. # Create template members
  111. def addgroup(member, group):
  112. g = Group.query.filter_by(name=group).first()
  113. if g is not None:
  114. member.groups.append(g)
  115. m = Member("PlanèteCasio", "contact@planet-casio.com", "nologin")
  116. addgroup(m, "Compte communautaire")
  117. addgroup(m, "No login")
  118. db.session.add(m)
  119. m = Member("GLaDOS", "glados@aperture.science", "nologin")
  120. m.xp = 1338
  121. addgroup(m, "Robot")
  122. addgroup(m, "No login")
  123. db.session.add(m)
  124. db.session.commit()
  125. db.session.add(SpecialPrivilege(m, "edit-posts"))
  126. db.session.add(SpecialPrivilege(m, "shoutbox-ban"))
  127. db.session.commit()
  128. print(f"Created 2 test members with some privileges.")
  129. def create_trophies():
  130. # Clean up trophies
  131. trophies("clear")
  132. # Create base trophies
  133. tr = []
  134. with open(os.path.join(app.root_path, "data", "trophies.yaml")) as fp:
  135. tr = yaml.safe_load(fp.read())
  136. for t in tr:
  137. description = t.get("description", "")
  138. if t["is_title"]:
  139. trophy = Title(t["name"], description, t["hidden"],
  140. t.get("css", ""))
  141. else:
  142. trophy = Trophy(t["name"], description, t["hidden"])
  143. db.session.add(trophy)
  144. db.session.commit()
  145. print(f"Created {len(tr)} trophies.")
  146. # Create their icons in /app/static/images/trophies
  147. names = [ slugify.slugify(t["name"]) for t in tr ]
  148. src = os.path.join(app.root_path, "data", "trophies.png")
  149. dst = os.path.join(app.root_path, "static", "images", "trophies")
  150. try:
  151. os.mkdir(dst)
  152. except FileExistsError:
  153. pass
  154. img = Image.open(src)
  155. def trophy_iterator(img):
  156. for y in range(img.height // 26):
  157. for x in range(img.width // 26):
  158. icon = img.crop((26*x+1, 26*y+1, 26*x+25, 26*y+25))
  159. # Skip blank squares in the source image
  160. if len(icon.getcolors()) > 1:
  161. yield icon.resize((48,48))
  162. for (name, icon) in zip(names, trophy_iterator(img)):
  163. icon.save(os.path.join(dst, f"{name}.png"))
  164. def create_forums():
  165. # Clean up forums
  166. forums("clear")
  167. # Create the forum tree
  168. fr = []
  169. success = 0
  170. with open(os.path.join(app.root_path, "data", "forums.yaml")) as fp:
  171. fr = yaml.safe_load(fp.read())
  172. for url, f in fr.items():
  173. if url == "/":
  174. parent = None
  175. else:
  176. parent_url = url.rsplit('/', 1)[0]
  177. if parent_url == "":
  178. parent_url = "/"
  179. parent = Forum.query.filter_by(url=parent_url).first()
  180. if parent is None:
  181. print(f"error: no parent with url {parent_url} for {url}")
  182. continue
  183. f = Forum(url, f['name'], f['prefix'], f.get('descr', ''), parent)
  184. db.session.add(f)
  185. success += 1
  186. db.session.commit()
  187. print(f"Created {success} forums.")
  188. def add_group(member, group):
  189. if group[0] != "#":
  190. print(f"error: group id {group} should start with '#'")
  191. return
  192. gid = int(group[1:])
  193. norm = unicode_names.normalize(member)
  194. g = Group.query.filter_by(id=gid).first()
  195. m = Member.query.filter_by(norm=norm).first()
  196. if m is None:
  197. print(f"error: no member has a normalized name of '{norm}'")
  198. return
  199. m.groups.append(g)
  200. db.session.add(m)
  201. db.session.commit()
  202. #
  203. # Main program
  204. #
  205. print(help_msg)
  206. commands = {
  207. "exit": lambda: sys.exit(0),
  208. "members": members,
  209. "groups": groups,
  210. "trophies": trophies,
  211. "trophy-members": trophy_members,
  212. "forums": forums,
  213. "create-groups-and-privs": create_groups_and_privs,
  214. "create-trophies": create_trophies,
  215. "create-forums": create_forums,
  216. "add-group": add_group,
  217. }
  218. while True:
  219. try:
  220. print("@> ", end="")
  221. cmd = input().split()
  222. except EOFError:
  223. sys.exit(0)
  224. if not cmd:
  225. continue
  226. if cmd[0] not in commands:
  227. print(f"error: unknown command '{cmd[0]}'")
  228. else:
  229. commands[cmd[0]](*cmd[1:])