Compare commits
5 Commits
modpol_mas
...
storage
Author | SHA1 | Date | |
---|---|---|---|
0725e66261 | |||
3824399f33 | |||
1f88981112 | |||
fcf0725534 | |||
3d8e4fb947 |
6
.gitignore
vendored
6
.gitignore
vendored
@ -1,5 +1 @@
|
|||||||
*/data/*
|
*/data
|
||||||
!*/data/placeholder
|
|
||||||
|
|
||||||
# ignore Mastodon credentials
|
|
||||||
modpol_mastodon/creds/
|
|
75
README.md
75
README.md
@ -1,43 +1,39 @@
|
|||||||
# Modpol
|
# Modpol for Minetest
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Modpol, short for "modular politics," enables diverse governance processes on multi-user platforms. It offers a library with which users can choose, modify, and create modules that add specific governance functionalities.
|
Modpol, short for "modular politics," enables diverse governance processes on multi-user platforms. It offers a library with which users can choose, modify, and create modules that add specific governance functionalities.
|
||||||
|
|
||||||
**Learn more at [modpol.net](https://modpol.net).**
|
This implementation is a mod for [Minetest](https://minetest.net), a free/open-source voxel game. It is designed to be adapted to other multi-user platforms that also employ Lua as an extension language.
|
||||||
|
|
||||||
## Modpol for Minetest
|
## How to use it
|
||||||
|
|
||||||
This implementation is a mod for [Minetest](https://minetest.net), a free/open-source voxel game. To use in Minetest, simply install the full codebase in your `mods/` or `worldmods/` folder. Minetest will load `init.lua`.
|
Modpol is built around groups called *orgs*. At the base is an org with all users in it, called `Root` by default. *Modules* enable people to do things within orgs, such as decide on membership, grant powers to the org, and much more. To get started in Minetest:
|
||||||
|
|
||||||
|
* Type the command `/mp`
|
||||||
|
* Select the org `Root`
|
||||||
|
* Choose one of its modules to make new orgs and craft their behavior
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Modules can be nested in each other, so one module can rely on another module to accomplish a process. Users might use a module to unilaterally carry out actions in the game, or the module might require a group decision to do so. Users can also change the modules available to users of a given org. There are currently two ways of doing this:
|
||||||
|
|
||||||
|
* Admins can remove modules from the list of modules loaded in `modpol_core/api.lua` and `modpol_minetest/api.lua`. This will make those modules no longer available to any user.
|
||||||
|
* Players can change the modules available in a given org from within the program using the `Change modules` module. Removed modules can be re-added in any org by using `Change modules` again.
|
||||||
|
|
||||||
|
Modpol should give you the ability to do whatever kind of politics you want with your modules. If there is something you would like to do that is not available, [develop a module for it](https://gitlab.com/medlabboulder/modpol/-/wikis/Module-Writing-Guide) (or ask us for help!).
|
||||||
|
|
||||||
|
|
||||||
|
## Installation in Minetest
|
||||||
|
|
||||||
|
To use this in Minetest, simply install it in your `mods/` or `worldmods/` folder. Minetest will load `init.lua`.
|
||||||
|
|
||||||
In the game, open the Modpol dashboard with the command `/mp`.
|
In the game, open the Modpol dashboard with the command `/mp`.
|
||||||
|
|
||||||
For testing purposes, players with the `privs` privilege (generally admins) can use the `/mptest` command, which resets all the orgs and opens a dashboard.
|
For testing purposes, players with the `privs` privilege (generally admins) can use the `/mp` command, which resets all the orgs and opens a dashboard.\
|
||||||
|
|
||||||
## Mastodon Govbot
|
|
||||||
|
|
||||||
Modpol can operate a governance-supporting bot for communities on [Mastodon](https://joinmastodon.org), an open social network.
|
## Standalone Version on the Command Line
|
||||||
|
|
||||||
This version utilizes and requires the installation of [lupa](https://github.com/scoder/lupa), which integrates Lua into Python, and [Mastodon.py](https://pypi.org/project/Mastodon.py/), a Python library for interacting with the Mastodon API.
|
Modpol can also be used independently of Minetest as a command-line tool. Currently command-line use of modpol requires a Unix-style system, but it is intended to become more fully platform independent.
|
||||||
|
|
||||||
*To do: explain how to set up the bot on the server.*
|
|
||||||
|
|
||||||
* Install Python on your system and the two required libraries:
|
|
||||||
- `pip install lupa`
|
|
||||||
- `pip install Mastodon.py`
|
|
||||||
* Set up files `clientcred.secret` and `usercred.secret` in the `modpol_mastodon/creds/` directory, using the account settings in Mastodon
|
|
||||||
|
|
||||||
Once it is configured, to initialize the bot, run from Modpol's base directory:
|
|
||||||
|
|
||||||
```
|
|
||||||
python govbot.py
|
|
||||||
```
|
|
||||||
|
|
||||||
This in turn calls login-mastodon.py, which initializes Modpol and the bot.
|
|
||||||
|
|
||||||
## Command Line
|
|
||||||
|
|
||||||
Modpol can also be used as a command-line tool. Currently command-line use of modpol requires a Unix-style system, but it is intended to become more fully platform independent.
|
|
||||||
|
|
||||||
The command-line version is in the `modpol` subdirectory. To run the program on Unix systems in CLI mode, install lua or luajit and execute the following in this directory:
|
The command-line version is in the `modpol` subdirectory. To run the program on Unix systems in CLI mode, install lua or luajit and execute the following in this directory:
|
||||||
|
|
||||||
@ -56,12 +52,25 @@ In the interpreter, for a list of global functions and tables, use `modpol.menu(
|
|||||||
|
|
||||||
## Storage
|
## Storage
|
||||||
|
|
||||||
The persistent storage method may be chosen in `modpol.lua`.
|
The persistent storage method may be chosen in `modpol.lua`. If available, Modpol uses Minetest's built-in StorageRef system for Minetest 5.*. If that is not available, or in CLI mode, data will be stored in a data directory at `modpol_core/data/`. This will contain a log file and serialized program data files.
|
||||||
|
|
||||||
By default, data will be stored in a data directory at `modpol_core/data/`. This will contain a log file and serialized program data files.
|
|
||||||
|
|
||||||
For Minetest: If available, Modpol uses Minetest's built-in StorageRef system for Minetest 5.*.
|
## Design philosophy
|
||||||
|
|
||||||
|
Modpol seeks to implement a theoretical framework called "[modular politics](https://metagov.org/modpol)," which proposes these design goals:
|
||||||
|
|
||||||
|
* *Modularity*: Platform operators and community members should have the ability to construct systems by creating, importing, and arranging composable parts together as a coherent whole.
|
||||||
|
* *Expressiveness*: The governance layer should be able to implement as wide a range of processes as possible.
|
||||||
|
* *Portability*: Governance tools developed for one platform should be portable to another platform for reuse and adaptation.
|
||||||
|
* *Interoperability*: Governance systems operating on different platforms and protocols should have the ability to interact with each other, sharing data and influencing each other's processes.
|
||||||
|
|
||||||
|
Additionally, Modpol seeks to counteract the tendency for "[implicit feudalism](https://ntnsndr.in/ImplicitFeudalism)," according to which rigid, top-down power structures are the norm in online spaces. To this end, some design patterns include:
|
||||||
|
|
||||||
|
* *Groups, not roles*: While most platforms assign powers through particular permissions given to individuals, in Modpol, power lies in groups (which Modpol calls "orgs").
|
||||||
|
* *Consent, not oligarchy*: Rather than assuming that decisions will be made by a few power-holders, the software assumes that consent by all affected users is the norm.
|
||||||
|
* *Inheritance, not blank slates*: When a new group is formed, it inherits the patterns of what preceded it, rather than imagining that it is starting from scratch.
|
||||||
|
|
||||||
|
It is certainly possible to use Modpol to replicate practices of implicit feudalism, such as all-powerful admins, but doing so requires extra work to overcome these defaults.
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
@ -92,7 +101,7 @@ We are grateful for initial support for this project from a residency with [The
|
|||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
We'd love to welcome more contributors. Please join the conversation in the [Issues](https://gitlab.com/medlabboulder/modpol/-/issues), the \#modpol channel at the [Metagovernance Project](https://metagov.org) Slack, and the [Minetest.net forum](https://forum.minetest.net/viewtopic.php?f=47&t=26037).
|
We'd love to welcome more contributors. Please join the conversation in the [Issues](https://gitlab.com/medlabboulder/modpol/-/issues), our [Matrix.org channel](https://matrix.to/#/#minetest-modpol:matrix.org), and the [Minetest.net forum](https://forum.minetest.net/viewtopic.php?f=47&t=26037).
|
||||||
|
|
||||||
Learn more about the project and how to develop your own modules in [the wiki](https://gitlab.com/medlabboulder/modpol/-/wikis/home).
|
Learn more about the project and how to develop your own modules in [the wiki](https://gitlab.com/medlabboulder/modpol/-/wikis/home).
|
||||||
|
|
||||||
|
113
govbot.py
113
govbot.py
@ -1,113 +0,0 @@
|
|||||||
# MODPOL GOVBOT
|
|
||||||
# A Python bridge between Modpol and Mastodon
|
|
||||||
|
|
||||||
## Initialize Modpol ##
|
|
||||||
|
|
||||||
import lupa
|
|
||||||
|
|
||||||
# Create a Lua runtime
|
|
||||||
lua = lupa.LuaRuntime(unpack_returned_tuples=True)
|
|
||||||
|
|
||||||
# Load your Lua script
|
|
||||||
script_path = 'login_mastodon.lua'
|
|
||||||
with open(script_path, 'r') as f:
|
|
||||||
lua.execute(f.read())
|
|
||||||
|
|
||||||
print("Loaded Modpol into Govbot")
|
|
||||||
|
|
||||||
# To do: load all override files
|
|
||||||
|
|
||||||
# If your Lua script defines functions, you can call them from Python
|
|
||||||
#result = lua.globals().your_function_name() # Replace with your actual function name
|
|
||||||
|
|
||||||
#print("Result from Lua:", result)
|
|
||||||
|
|
||||||
|
|
||||||
## Initialize Mastodon ##
|
|
||||||
|
|
||||||
from mastodon import Mastodon
|
|
||||||
# ^ https://mastodonpy.readthedocs.io/en/stable/#
|
|
||||||
import time
|
|
||||||
import datetime
|
|
||||||
# ^ https://github.com/HikaruSama233/mastodon_autoreply_bot_template/blob/main/bot_template.py
|
|
||||||
|
|
||||||
# Variables
|
|
||||||
## Character maximum for the server
|
|
||||||
char_max = 500
|
|
||||||
|
|
||||||
# Connect to Mastodon
|
|
||||||
govbot = Mastodon(
|
|
||||||
client_id='modpol_mastodon/creds/clientcred.secret',
|
|
||||||
access_token = 'modpol_mastodon/creds/usercred.secret')
|
|
||||||
|
|
||||||
print("Signed in to Mastodon")
|
|
||||||
|
|
||||||
# Handle notification events
|
|
||||||
def handle_event(event):
|
|
||||||
print("{} Handling notification ".format(datetime.datetime.now())
|
|
||||||
+ str(event['id']))
|
|
||||||
if 'mention' in event['type']:
|
|
||||||
mention_username = event['account']['username']
|
|
||||||
print(str(event['id']) + ": mention from @"
|
|
||||||
+ mention_username)
|
|
||||||
# Command handling
|
|
||||||
# perhaps move this to a separate Interfaces file
|
|
||||||
if "!dashboard" in event['status']['content']:
|
|
||||||
govbot.status_reply(event['status'],
|
|
||||||
"[dashboard here]")
|
|
||||||
print("{} Replied to ".format(datetime.datetime.now())
|
|
||||||
+ str(event['id']))
|
|
||||||
# To do: if DM
|
|
||||||
else:
|
|
||||||
govbot.status_reply(event['status'],
|
|
||||||
"Thanks for mentioning me!")
|
|
||||||
print("{} Replied to ".format(datetime.datetime.now())
|
|
||||||
+ str(event['id']))
|
|
||||||
## ADD OTHER IF STATEMENTS HERE
|
|
||||||
else:
|
|
||||||
govbot.status_reply(event['status'],
|
|
||||||
"I'm not sure how to parse that.")
|
|
||||||
print("{} Posted error message ".format(datetime.datetime.now())
|
|
||||||
+ str(event['id']))
|
|
||||||
|
|
||||||
# Check notifications
|
|
||||||
events_queue = {}
|
|
||||||
def check_events():
|
|
||||||
notifications = govbot.notifications(mentions_only=True)
|
|
||||||
current_time = datetime.datetime.now()
|
|
||||||
if len(notifications) > 0:
|
|
||||||
print("{} Total notifications {}".format(current_time, len(notifications)))
|
|
||||||
events_queue = notifications
|
|
||||||
while len(events_queue) > 0:
|
|
||||||
id = events_queue[0]['id']
|
|
||||||
handle_event(events_queue.pop(0)) # removes event from queue
|
|
||||||
govbot.notifications_dismiss(id)
|
|
||||||
elif str(current_time.minute) == '0':
|
|
||||||
print("{} No notifications".format(current_time))
|
|
||||||
|
|
||||||
# Initialization
|
|
||||||
|
|
||||||
# Delete past posts (while we are testing)
|
|
||||||
## Get account information
|
|
||||||
account_info = govbot.account_verify_credentials()
|
|
||||||
## Extract and print account ID
|
|
||||||
acc_id = account_info['id']
|
|
||||||
## Fetch the bot's posts
|
|
||||||
old_posts = govbot.account_statuses(id=acc_id)
|
|
||||||
## Delete
|
|
||||||
for post in old_posts:
|
|
||||||
govbot.status_delete(id=post.id)
|
|
||||||
# Delete past notifications
|
|
||||||
govbot.notifications_clear()
|
|
||||||
|
|
||||||
print("{} Initialized".format(datetime.datetime.now()))
|
|
||||||
|
|
||||||
first_post = "Commands:"
|
|
||||||
first_post += "\n!dashboard: View dashboard"
|
|
||||||
govbot.status_post(first_post[:char_max])
|
|
||||||
|
|
||||||
while 1:
|
|
||||||
# Check every 5 seconds
|
|
||||||
time.sleep(5)
|
|
||||||
if len(events_queue) == 0:
|
|
||||||
check_events()
|
|
Binary file not shown.
Before Width: | Height: | Size: 588 KiB |
@ -1,2 +0,0 @@
|
|||||||
dofile("modpol_core/modpol.lua")
|
|
||||||
|
|
@ -12,22 +12,27 @@ dofile (localdir .. "/interactions/interactions.lua")
|
|||||||
|
|
||||||
--modules
|
--modules
|
||||||
--TODO make this automatic and directory-based
|
--TODO make this automatic and directory-based
|
||||||
dofile (localdir .. "/modules/add_child_org.lua")
|
dofile (localdir .. "/storage/store-modules.lua")
|
||||||
dofile (localdir .. "/modules/change_modules.lua")
|
modpol.load_modules(localdir .. "/modules")
|
||||||
dofile (localdir .. "/modules/change_policy.lua")
|
|
||||||
dofile (localdir .. "/modules/consent.lua")
|
-- dofile (localdir .. "/modules/add_child_org_consent.lua")
|
||||||
dofile (localdir .. "/modules/create_token.lua")
|
-- dofile (localdir .. "/modules/add_child_org.lua")
|
||||||
dofile (localdir .. "/modules/defer.lua")
|
-- dofile (localdir .. "/modules/change_modules.lua")
|
||||||
dofile (localdir .. "/modules/display_policies.lua")
|
-- dofile (localdir .. "/modules/change_policy.lua")
|
||||||
dofile (localdir .. "/modules/display_processes.lua")
|
-- dofile (localdir .. "/modules/consent.lua")
|
||||||
dofile (localdir .. "/modules/join_org.lua")
|
-- dofile (localdir .. "/modules/create_token.lua")
|
||||||
dofile (localdir .. "/modules/leave_org.lua")
|
-- dofile (localdir .. "/modules/defer_consent.lua")
|
||||||
dofile (localdir .. "/modules/message_org.lua")
|
-- dofile (localdir .. "/modules/display_policies.lua")
|
||||||
dofile (localdir .. "/modules/randomizer.lua")
|
-- dofile (localdir .. "/modules/display_processes.lua")
|
||||||
dofile (localdir .. "/modules/remove_child_org.lua")
|
-- dofile (localdir .. "/modules/join_org_consent.lua")
|
||||||
dofile (localdir .. "/modules/remove_member.lua")
|
-- dofile (localdir .. "/modules/leave_org.lua")
|
||||||
dofile (localdir .. "/modules/remove_org.lua")
|
-- dofile (localdir .. "/modules/message_org.lua")
|
||||||
dofile (localdir .. "/modules/remove_process.lua")
|
-- dofile (localdir .. "/modules/randomizer.lua")
|
||||||
dofile (localdir .. "/modules/rename_org.lua")
|
-- dofile (localdir .. "/modules/remove_child_consent.lua")
|
||||||
dofile (localdir .. "/modules/send_token.lua")
|
-- dofile (localdir .. "/modules/remove_member_consent.lua")
|
||||||
dofile (localdir .. "/modules/tokenomics.lua")
|
-- dofile (localdir .. "/modules/remove_org_consent.lua")
|
||||||
|
-- dofile (localdir .. "/modules/remove_org.lua")
|
||||||
|
-- dofile (localdir .. "/modules/remove_process.lua")
|
||||||
|
-- dofile (localdir .. "/modules/rename_org_consent.lua")
|
||||||
|
-- dofile (localdir .. "/modules/send_token.lua")
|
||||||
|
-- dofile (localdir .. "/modules/tokenomics.lua")
|
||||||
|
@ -26,13 +26,9 @@ function modpol.interactions.get_policy_string(
|
|||||||
if this_org.policies[module_slug][k] then
|
if this_org.policies[module_slug][k] then
|
||||||
this_policy =
|
this_policy =
|
||||||
tostring(this_org.policies[module_slug][k])
|
tostring(this_org.policies[module_slug][k])
|
||||||
else
|
|
||||||
if not v then
|
|
||||||
this_policy = "none"
|
|
||||||
else
|
else
|
||||||
this_policy = tostring(v)
|
this_policy = tostring(v)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
table.insert(output, k.." - "..this_policy)
|
table.insert(output, k.." - "..this_policy)
|
||||||
end
|
end
|
||||||
return "Policies:\n" .. table.concat(output, sep)
|
return "Policies:\n" .. table.concat(output, sep)
|
||||||
@ -123,7 +119,7 @@ function modpol.interactions.dashboard(user)
|
|||||||
print("Orgs and users reset")
|
print("Orgs and users reset")
|
||||||
modpol.interactions.dashboard(user)
|
modpol.interactions.dashboard(user)
|
||||||
|
|
||||||
elseif sel == "Q" or sel == "q" then
|
elseif sel == "Q" or "q" then
|
||||||
return
|
return
|
||||||
|
|
||||||
else
|
else
|
||||||
@ -152,10 +148,8 @@ function modpol.interactions.org_dashboard(user, org_string)
|
|||||||
local children = {}
|
local children = {}
|
||||||
for k,v in ipairs(org.children) do
|
for k,v in ipairs(org.children) do
|
||||||
local this_child = modpol.orgs.get_org(v)
|
local this_child = modpol.orgs.get_org(v)
|
||||||
if this_child then
|
|
||||||
table.insert(children, this_child.name)
|
table.insert(children, this_child.name)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
-- prepare modules menu
|
-- prepare modules menu
|
||||||
local modules = {}
|
local modules = {}
|
||||||
@ -171,13 +165,7 @@ function modpol.interactions.org_dashboard(user, org_string)
|
|||||||
table.sort(modules)
|
table.sort(modules)
|
||||||
|
|
||||||
-- list pending
|
-- list pending
|
||||||
local processes = {}
|
local process_msg = #org.processes .. " total processes"
|
||||||
for i,v in ipairs(org.processes) do
|
|
||||||
if v ~= "deleted" then
|
|
||||||
processes[i] = org.processes[i]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local process_msg = #processes .. " total processes"
|
|
||||||
if org.pending[user] then
|
if org.pending[user] then
|
||||||
process_msg = process_msg .. " (" ..
|
process_msg = process_msg .. " (" ..
|
||||||
modpol.util.num_pairs(org.pending[user]) .. " pending)"
|
modpol.util.num_pairs(org.pending[user]) .. " pending)"
|
||||||
@ -219,7 +207,6 @@ function modpol.interactions.org_dashboard(user, org_string)
|
|||||||
org.name, module.slug, "\n")..
|
org.name, module.slug, "\n")..
|
||||||
"\n".."Proceed?",
|
"\n".."Proceed?",
|
||||||
function(input)
|
function(input)
|
||||||
print("\n")
|
|
||||||
if input == "Yes" then
|
if input == "Yes" then
|
||||||
org:call_module(module_sel, user)
|
org:call_module(module_sel, user)
|
||||||
elseif input == "No" then
|
elseif input == "No" then
|
||||||
@ -232,9 +219,11 @@ function modpol.interactions.org_dashboard(user, org_string)
|
|||||||
modpol.interactions.org_dashboard(user, org.id)
|
modpol.interactions.org_dashboard(user, org.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
elseif sel == 'p' or sel == 'P' then -- Pending processes
|
elseif sel == 'p' or sel == 'P' then
|
||||||
|
local processes = {}
|
||||||
print("All processes: (* indicates pending)")
|
print("All processes: (* indicates pending)")
|
||||||
for i,v in ipairs(processes) do
|
for i,v in ipairs(org.processes) do
|
||||||
|
if v ~= "deleted" then
|
||||||
local active = ''
|
local active = ''
|
||||||
if org.pending[user] then
|
if org.pending[user] then
|
||||||
if org.pending[user][v.id] then
|
if org.pending[user][v.id] then
|
||||||
@ -243,6 +232,7 @@ function modpol.interactions.org_dashboard(user, org_string)
|
|||||||
end
|
end
|
||||||
print("["..v.id.."] "..v.slug..active)
|
print("["..v.id.."] "..v.slug..active)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
print()
|
print()
|
||||||
print("Interact with which one (use [id] number)?")
|
print("Interact with which one (use [id] number)?")
|
||||||
local to_interact = io.read()
|
local to_interact = io.read()
|
||||||
@ -257,7 +247,6 @@ function modpol.interactions.org_dashboard(user, org_string)
|
|||||||
if org.pending[user][process.id] then
|
if org.pending[user][process.id] then
|
||||||
org:interact(process.id, user)
|
org:interact(process.id, user)
|
||||||
end
|
end
|
||||||
modpol.interactions.org_dashboard(user, org.id)
|
|
||||||
end
|
end
|
||||||
elseif sel == 'b' or sel == 'B' then
|
elseif sel == 'b' or sel == 'B' then
|
||||||
modpol.interactions.dashboard(user)
|
modpol.interactions.dashboard(user)
|
||||||
@ -348,14 +337,14 @@ function modpol.interactions.display(user, title, message, completion)
|
|||||||
modpol.interactions.message(
|
modpol.interactions.message(
|
||||||
self.initiator, "Error: input not typed for display")
|
self.initiator, "Error: input not typed for display")
|
||||||
if completion then completion() else
|
if completion then completion() else
|
||||||
modpol.interactions.dashboard(user)
|
modpol.intereactions.dashboard(user)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
print(message)
|
print(message)
|
||||||
print("\nEnter to continue")
|
print("\nEnter to continue")
|
||||||
io.read()
|
io.read()
|
||||||
if completion then completion() else
|
if completion then completion() else
|
||||||
modpol.interactions.dashboard(user)
|
modpol.intereactions.dashboard(user)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -478,8 +467,10 @@ function modpol.interactions.binary_poll_user(user, question, func)
|
|||||||
answer = io.read()
|
answer = io.read()
|
||||||
until answer == "y" or answer == "n"
|
until answer == "y" or answer == "n"
|
||||||
if answer == "y" then
|
if answer == "y" then
|
||||||
|
modpol.interactions.message(user, "Response recorded")
|
||||||
func("Yes")
|
func("Yes")
|
||||||
elseif answer == "n" then
|
elseif answer == "n" then
|
||||||
|
modpol.interactions.message(user, "Response recorded")
|
||||||
func("No")
|
func("No")
|
||||||
else
|
else
|
||||||
modpol.interactions.message(user, "Error: invalid response")
|
modpol.interactions.message(user, "Error: invalid response")
|
||||||
|
@ -55,7 +55,7 @@ dofile (topdir .. "/util/misc.lua")
|
|||||||
-- Select a storage method
|
-- Select a storage method
|
||||||
-- -- preferably, declare this in the init.lua that calls modpol.lua This is the default.
|
-- -- preferably, declare this in the init.lua that calls modpol.lua This is the default.
|
||||||
-- Works with CLI:
|
-- Works with CLI:
|
||||||
modpol.storage_file_path = modpol.storage_file_path or topdir .. "/storage/storage-local.lua"
|
modpol.storage_file_path = modpol.storage_file_path or topdir .. "/storage/unix-storage.lua"
|
||||||
-- Works with Minetest 5:
|
-- Works with Minetest 5:
|
||||||
--modpol.storage_file_path = modpol.storage_file_path or topdir .. "/storage/storage-mod_storage.lua")
|
--modpol.storage_file_path = modpol.storage_file_path or topdir .. "/storage/storage-mod_storage.lua")
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
--- Adds a child org
|
--- Adds a child org.
|
||||||
-- @module add_child_org
|
-- @module add_child_org
|
||||||
|
|
||||||
local add_child_org = {
|
local add_child_org = {
|
||||||
@ -8,10 +8,9 @@ local add_child_org = {
|
|||||||
}
|
}
|
||||||
add_child_org.data = {
|
add_child_org.data = {
|
||||||
child_name = "",
|
child_name = "",
|
||||||
result = false
|
result = nil
|
||||||
}
|
}
|
||||||
add_child_org.config = {
|
add_child_org.config = {
|
||||||
approval_module = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Initiate consent for new child org
|
--- Initiate consent for new child org
|
||||||
@ -43,34 +42,22 @@ function add_child_org:initiate(result)
|
|||||||
modpol.interactions.message(
|
modpol.interactions.message(
|
||||||
self.initiator,
|
self.initiator,
|
||||||
"Proposed child org: " .. input)
|
"Proposed child org: " .. input)
|
||||||
-- initiate consent process
|
-- create the org
|
||||||
self.data.result = result
|
|
||||||
self:call_module(
|
|
||||||
self.config.approval_module,
|
|
||||||
self.initiator,
|
|
||||||
{
|
|
||||||
prompt = "Create child org " ..
|
|
||||||
self.data.child_name .. "?",
|
|
||||||
votes_required = #self.org.members
|
|
||||||
},
|
|
||||||
function()
|
|
||||||
self:create_child_org()
|
self:create_child_org()
|
||||||
end
|
|
||||||
)
|
|
||||||
modpol.interactions.org_dashboard(
|
modpol.interactions.org_dashboard(
|
||||||
self.initiator, self.org.name)
|
self.initiator, self.org.name)
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Create a new child org
|
--- Create a new child orgg
|
||||||
-- @function add_child_org:create_child_org
|
-- @function add_child_org:create_child_org
|
||||||
function add_child_org:create_child_org()
|
function add_child_org:create_child_org()
|
||||||
self.org:add_org(self.data.child_name, self.initiator)
|
self.org:add_org(self.data.child_name, self.initiator)
|
||||||
modpol.interactions.message_org(
|
modpol.interactions.message_org(
|
||||||
self.initiator,
|
self.initiator,
|
||||||
self.org.name,
|
self.org.name,
|
||||||
"Created child org in " .. self.org.name .. ": "
|
"Created child org "
|
||||||
..self.data.child_name)
|
..self.data.child_name)
|
||||||
if self.data.result then self.data.result() end
|
if self.data.result then self.data.result() end
|
||||||
self.org:delete_process(self.id)
|
self.org:delete_process(self.id)
|
||||||
|
78
modpol_core/modules/add_child_org_consent.lua
Normal file
78
modpol_core/modules/add_child_org_consent.lua
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
--- Adds a child org.
|
||||||
|
-- Depends on `consent`
|
||||||
|
-- @module add_child_org_consent
|
||||||
|
|
||||||
|
local add_child_org_consent = {
|
||||||
|
name = "Add child org (consent)",
|
||||||
|
slug = "add_child_org_consent",
|
||||||
|
desc = "Create a child org in the current one with member consent"
|
||||||
|
}
|
||||||
|
add_child_org_consent.data = {
|
||||||
|
child_name = "",
|
||||||
|
result = nil
|
||||||
|
}
|
||||||
|
add_child_org_consent.config = {
|
||||||
|
}
|
||||||
|
|
||||||
|
--- Initiate consent for new child org
|
||||||
|
-- @function add_child_org_consent:initiate(result)
|
||||||
|
-- @param result Callback if this module is embedded in other modules
|
||||||
|
function add_child_org_consent:initiate(result)
|
||||||
|
modpol.interactions.text_query(
|
||||||
|
self.initiator,"Child org name: ",
|
||||||
|
function(input)
|
||||||
|
if input == "" then
|
||||||
|
modpol.interactions.message(
|
||||||
|
self.initiator,
|
||||||
|
"No name entered for child org")
|
||||||
|
modpol.interactions.org_dashboard(
|
||||||
|
self.initiator, self.org.name)
|
||||||
|
self.org:delete_process(self.id)
|
||||||
|
return
|
||||||
|
elseif modpol.orgs.get_org(input) then
|
||||||
|
modpol.interactions.message(
|
||||||
|
self.initiator,
|
||||||
|
"Org name already in use")
|
||||||
|
modpol.interactions.org_dashboard(
|
||||||
|
self.initiator, self.org.name)
|
||||||
|
self.org:delete_process(self.id)
|
||||||
|
if result then result() end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
self.data.child_name = input
|
||||||
|
modpol.interactions.message(
|
||||||
|
self.initiator,
|
||||||
|
"Proposed child org: " .. input)
|
||||||
|
-- initiate consent process
|
||||||
|
self:call_module(
|
||||||
|
"consent",
|
||||||
|
self.initiator,
|
||||||
|
{
|
||||||
|
prompt = "Create child org " ..
|
||||||
|
self.data.child_name .. "?",
|
||||||
|
votes_required = #self.org.members
|
||||||
|
},
|
||||||
|
function()
|
||||||
|
self:create_child_org()
|
||||||
|
end
|
||||||
|
)
|
||||||
|
modpol.interactions.org_dashboard(
|
||||||
|
self.initiator, self.org.name)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Create a new child orgg
|
||||||
|
-- @function add_child_org_consent:create_child_org
|
||||||
|
function add_child_org_consent:create_child_org()
|
||||||
|
self.org:add_org(self.data.child_name, self.initiator)
|
||||||
|
modpol.interactions.message_org(
|
||||||
|
self.initiator,
|
||||||
|
self.org.name,
|
||||||
|
"Consent reached: created child org "
|
||||||
|
..self.data.child_name)
|
||||||
|
if self.data.result then self.data.result() end
|
||||||
|
self.org:delete_process(self.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
modpol.modules.add_child_org_consent = add_child_org_consent
|
@ -1,10 +1,11 @@
|
|||||||
--- change_modules
|
--- change_modules
|
||||||
|
-- Depends on consent
|
||||||
-- @module change_modules
|
-- @module change_modules
|
||||||
|
|
||||||
local change_modules = {
|
local change_modules = {
|
||||||
name = "Change modules",
|
name = "Change modules (consent)",
|
||||||
slug = "change_modules",
|
slug = "change_modules",
|
||||||
desc = "Add or remove modules from the org",
|
desc = "Add or remove modules from the org with member consent",
|
||||||
hide = false;
|
hide = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -16,7 +17,6 @@ change_modules.data = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
change_modules.config = {
|
change_modules.config = {
|
||||||
approval_module = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Initiate change in modules.
|
--- Initiate change in modules.
|
||||||
@ -68,7 +68,7 @@ function change_modules:initiate(result)
|
|||||||
self.org:delete_process(self.id)
|
self.org:delete_process(self.id)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
-- proceed with approval
|
-- proceed with consent
|
||||||
local query = "Accept module changes in org "..
|
local query = "Accept module changes in org "..
|
||||||
self.org.name.."?"
|
self.org.name.."?"
|
||||||
self.data.summary = ""
|
self.data.summary = ""
|
||||||
@ -80,10 +80,11 @@ function change_modules:initiate(result)
|
|||||||
table.concat(self.data.remove_modules,", ")
|
table.concat(self.data.remove_modules,", ")
|
||||||
end
|
end
|
||||||
self:call_module(
|
self:call_module(
|
||||||
self.config.approval_module,
|
"consent",
|
||||||
self.initiator,
|
self.initiator,
|
||||||
{
|
{
|
||||||
prompt = query..self.data.summary
|
prompt = query..self.data.summary,
|
||||||
|
votes_required = #self.org.members
|
||||||
},
|
},
|
||||||
function()
|
function()
|
||||||
self:implement_change()
|
self:implement_change()
|
||||||
|
@ -9,11 +9,11 @@ local change_policy = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
change_policy.data = {
|
change_policy.data = {
|
||||||
result = false
|
result = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
change_policy.config = {
|
change_policy.config = {
|
||||||
approval_module = false
|
approval = "none"
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Change modules initiate
|
--- Change modules initiate
|
||||||
@ -23,7 +23,8 @@ function change_policy:initiate(result)
|
|||||||
-- prepare module options
|
-- prepare module options
|
||||||
local available_modules = {}
|
local available_modules = {}
|
||||||
for k,org_mod in pairs(modpol.modules) do
|
for k,org_mod in pairs(modpol.modules) do
|
||||||
if self.org.policies[k] then
|
if not org_mod.hide and
|
||||||
|
self.org.policies[k] then
|
||||||
available_modules[org_mod.slug] = modpol.util.copy_table(org_mod)
|
available_modules[org_mod.slug] = modpol.util.copy_table(org_mod)
|
||||||
end end
|
end end
|
||||||
local modules_list = {}
|
local modules_list = {}
|
||||||
@ -68,20 +69,12 @@ function change_policy:initiate(result)
|
|||||||
self.initiator, "Choose a policy to change:",
|
self.initiator, "Choose a policy to change:",
|
||||||
policy_list,
|
policy_list,
|
||||||
function(policy_choice)
|
function(policy_choice)
|
||||||
local readable_value =
|
|
||||||
tostring(modpol.modules[mod_choice][policy_choice])
|
|
||||||
if readable_value == "nil" then
|
|
||||||
readable_value = "none"
|
|
||||||
end
|
|
||||||
modpol.interactions.text_query(
|
modpol.interactions.text_query(
|
||||||
self.initiator,
|
self.initiator,
|
||||||
"Current " .. policy_choice .. " value: "
|
"Current " .. policy_choice .. " value: " ..
|
||||||
.. readable_value
|
tostring(modpol.modules[mod_choice][policy_choice])
|
||||||
.. "\nChange value to (or leave blank):",
|
.. "\nChange value to (be careful!):",
|
||||||
function(policy_input)
|
function(policy_input)
|
||||||
if policy_input == "" then
|
|
||||||
policy_input = false
|
|
||||||
end
|
|
||||||
self:approve_change(
|
self:approve_change(
|
||||||
mod_choice,
|
mod_choice,
|
||||||
policy_choice,
|
policy_choice,
|
||||||
@ -101,24 +94,17 @@ end
|
|||||||
-- @param policy (string) policy slug
|
-- @param policy (string) policy slug
|
||||||
-- @param input (string) input content
|
-- @param input (string) input content
|
||||||
function change_policy:approve_change(module_slug, policy, input)
|
function change_policy:approve_change(module_slug, policy, input)
|
||||||
self.org:call_module(
|
-- NEED TO ADD APPROVAL CODE for consent, etc.
|
||||||
self.config.approval_module,
|
|
||||||
self.initiator,
|
|
||||||
{prompt = "Update " .. policy .. " policy on module " ..
|
|
||||||
module_slug .. " with: " .. input .. " ?"},
|
|
||||||
function()
|
|
||||||
modpol.interactions.message(
|
modpol.interactions.message(
|
||||||
self.initiator,
|
self.initiator,
|
||||||
"In ".. self.org.name .. " updating " .. policy ..
|
"Updating " .. policy .. " policy on module " ..
|
||||||
" policy on module " .. module_slug .. " with: " .. input)
|
module_slug .. " with: " .. input)
|
||||||
self.org.policies[module_slug][policy] = input
|
self.org.policies[module_slug][policy] = input
|
||||||
modpol.interactions.org_dashboard(
|
modpol.interactions.org_dashboard(
|
||||||
self.initiator, self.org.id)
|
self.initiator, self.org.id)
|
||||||
if self.data.result then self.data.result() end
|
if self.data.result then self.data.result() end
|
||||||
self.org:delete_process(self.id)
|
self.org:delete_process(self.id)
|
||||||
end,
|
return
|
||||||
self.id
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
modpol.modules.change_policy = change_policy
|
modpol.modules.change_policy = change_policy
|
||||||
|
@ -14,7 +14,7 @@ consent.data = {
|
|||||||
|
|
||||||
consent.config = {
|
consent.config = {
|
||||||
prompt = "Do you consent?",
|
prompt = "Do you consent?",
|
||||||
votes_required = false
|
votes_required = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Initiate consent
|
--- Initiate consent
|
||||||
@ -22,22 +22,13 @@ consent.config = {
|
|||||||
-- @param result Callback if this module is embedded in other modules
|
-- @param result Callback if this module is embedded in other modules
|
||||||
function consent:initiate(result)
|
function consent:initiate(result)
|
||||||
self.data.result = result
|
self.data.result = result
|
||||||
-- if org is empty or no votes required, consent given
|
-- if org is empty, consent is given automatically
|
||||||
if self.org:get_member_count() == 0
|
if self.org:get_member_count() == 0 then
|
||||||
or self.config.votes_required == 0 then
|
|
||||||
modpol.interactions.message_org(
|
|
||||||
self.initiator,
|
|
||||||
self.org.name,
|
|
||||||
"Consent reached: " .. self.config.prompt)
|
|
||||||
if self.data.result then
|
if self.data.result then
|
||||||
self.data.result() end
|
self.data.result() end
|
||||||
self.org:delete_process(self.id)
|
self.org:delete_process(self.id)
|
||||||
else
|
else
|
||||||
-- otherwise, create poll
|
-- otherwise, create poll
|
||||||
-- set default votes_required
|
|
||||||
if not self.config.votes_required then
|
|
||||||
self.config.votes_required = self.org:get_member_count()
|
|
||||||
end
|
|
||||||
for id, member in pairs(self.org.members) do
|
for id, member in pairs(self.org.members) do
|
||||||
self.org:add_pending_action(self.id, member, "callback")
|
self.org:add_pending_action(self.id, member, "callback")
|
||||||
end
|
end
|
||||||
@ -63,10 +54,6 @@ function consent:callback(member)
|
|||||||
"/"..self.config.votes_required..")"
|
"/"..self.config.votes_required..")"
|
||||||
)
|
)
|
||||||
if self.data.votes >= self.config.votes_required then
|
if self.data.votes >= self.config.votes_required then
|
||||||
modpol.interactions.message_org(
|
|
||||||
self.initiator,
|
|
||||||
self.org.name,
|
|
||||||
"Consent reached: " .. self.config.prompt)
|
|
||||||
if self.data.result then
|
if self.data.result then
|
||||||
self.data.result() end
|
self.data.result() end
|
||||||
self.org:delete_process(self.id)
|
self.org:delete_process(self.id)
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
-- @module create_token
|
-- @module create_token
|
||||||
|
|
||||||
local create_token = {
|
local create_token = {
|
||||||
name = "Create a token",
|
name = "Create a token (consent)",
|
||||||
slug = "create_token",
|
slug = "create_token",
|
||||||
desc = "Creates an org token",
|
desc = "With org consent, creates an org token",
|
||||||
hide = false;
|
hide = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13,8 +13,7 @@ create_token.data = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
create_token.config = {
|
create_token.config = {
|
||||||
token_name = "token",
|
token_name = ""
|
||||||
approval_module = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Initiate function
|
--- Initiate function
|
||||||
@ -30,7 +29,7 @@ function create_token:initiate(result)
|
|||||||
"tokenomics",
|
"tokenomics",
|
||||||
self.initiator,
|
self.initiator,
|
||||||
{
|
{
|
||||||
approval_module = self.config.approval_module,
|
consent = true,
|
||||||
token_slug = self.config.token_name
|
token_slug = self.config.token_name
|
||||||
},
|
},
|
||||||
function(input2)
|
function(input2)
|
||||||
|
@ -1,30 +1,30 @@
|
|||||||
--- Defer
|
--- Defer consent
|
||||||
-- @module defer
|
-- @module defer_consent
|
||||||
|
|
||||||
local defer = {
|
local defer_consent = {
|
||||||
name = "Defer ",
|
name = "Defer consent",
|
||||||
slug = "defer",
|
slug = "defer_consent",
|
||||||
desc = "Defers a decision to another org",
|
desc = "Defers consent on a decision to another org",
|
||||||
hide = true;
|
hide = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
defer.data = {
|
defer_consent.data = {
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Config for module
|
--- Config for module
|
||||||
-- @field defer_org Name or ID of target org
|
-- @field defer_org Name or ID of target org
|
||||||
-- @field approval_module module to use in target org
|
-- @field votes_required Threshold passed on to `consent`
|
||||||
-- @field prompt String passed on to approval_module
|
-- @field prompt String passed on to `consent`
|
||||||
defer.config = {
|
defer_consent.config = {
|
||||||
approval_module = "consent",
|
|
||||||
defer_org = "Root",
|
defer_org = "Root",
|
||||||
prompt = ""
|
votes_required = 1,
|
||||||
|
prompt = "Do you consent?"
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Initiate function
|
--- Initiate function
|
||||||
-- @param result Callback if this module is embedded in other modules
|
-- @param result Callback if this module is embedded in other modules
|
||||||
-- @function defer:initiate
|
-- @function defer_consent:initiate
|
||||||
function defer:initiate(result)
|
function defer_consent:initiate(result)
|
||||||
local defer_org = modpol.orgs.get_org(self.config.defer_org)
|
local defer_org = modpol.orgs.get_org(self.config.defer_org)
|
||||||
if not defer_org then
|
if not defer_org then
|
||||||
modpol.interactions.message(
|
modpol.interactions.message(
|
||||||
@ -32,21 +32,18 @@ function defer:initiate(result)
|
|||||||
self.org:delete_process(self.id)
|
self.org:delete_process(self.id)
|
||||||
else
|
else
|
||||||
defer_org:call_module(
|
defer_org:call_module(
|
||||||
self.config.approval_module,
|
"consent", self.initiator,
|
||||||
self.initiator,
|
|
||||||
{
|
{
|
||||||
|
votes_required = self.config.votes_required,
|
||||||
prompt = self.config.prompt
|
prompt = self.config.prompt
|
||||||
},
|
},
|
||||||
function()
|
function()
|
||||||
if result then result() end
|
if result then result() end
|
||||||
end)
|
end)
|
||||||
modpol.interactions.message(
|
|
||||||
self.initiator, "Defer: action sent to " .. defer_org.name)
|
|
||||||
end
|
end
|
||||||
modpol.interactions.org_dashboard(
|
if result then result() end
|
||||||
self.initiator, self.org.id)
|
|
||||||
self.org:delete_process(self.id)
|
self.org:delete_process(self.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- (Required) Add to module table
|
--- (Required) Add to module table
|
||||||
modpol.modules.defer = defer
|
modpol.modules.defer_consent = defer_consent
|
@ -29,15 +29,11 @@ function display_policies:initiate(result)
|
|||||||
v2 = self.org.policies[k][k2]
|
v2 = self.org.policies[k][k2]
|
||||||
end
|
end
|
||||||
local v2_string = ""
|
local v2_string = ""
|
||||||
if not v2 then
|
if type(v2) == "string" then
|
||||||
v2_string = "none"
|
|
||||||
elseif type(v2) == "string" then
|
|
||||||
v2_string = v2
|
v2_string = v2
|
||||||
elseif type(v2) == "table"
|
elseif type(v2) == "table"
|
||||||
or type(v2) == "number" then
|
or type(v2) == "number" then
|
||||||
v2_string = tostring(v2)
|
v2_string = tostring(v2)
|
||||||
elseif type(v2) == "boolean" then
|
|
||||||
v2_string = tostring(v2)
|
|
||||||
else
|
else
|
||||||
v2_string = "Could not render"
|
v2_string = "Could not render"
|
||||||
end
|
end
|
||||||
@ -57,10 +53,10 @@ function display_policies:initiate(result)
|
|||||||
"Policies in org "..self.org.name,
|
"Policies in org "..self.org.name,
|
||||||
output,
|
output,
|
||||||
function()
|
function()
|
||||||
self.org:delete_process(self.id)
|
|
||||||
modpol.interactions.org_dashboard(
|
modpol.interactions.org_dashboard(
|
||||||
self.initiator, self.org.id)
|
self.initiator, self.org.id)
|
||||||
if result then result() end
|
if result then result() end
|
||||||
|
self.org:delete_process(self.id)
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
@ -19,7 +19,7 @@ display_processes.config = {
|
|||||||
-- @param result Callback if this module is embedded in other modules
|
-- @param result Callback if this module is embedded in other modules
|
||||||
function display_processes:initiate(result)
|
function display_processes:initiate(result)
|
||||||
local display_table = {}
|
local display_table = {}
|
||||||
for k,v in ipairs(self.org.processes) do
|
for k,v in pairs(self.org.processes) do
|
||||||
if v ~= "deleted" then
|
if v ~= "deleted" then
|
||||||
local input = v.id..": "..v.slug
|
local input = v.id..": "..v.slug
|
||||||
table.insert(display_table, input)
|
table.insert(display_table, input)
|
||||||
|
3
modpol_core/modules/ignore.txt
Normal file
3
modpol_core/modules/ignore.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
change_modules-dropdown.lua
|
||||||
|
join_org.lua
|
||||||
|
template.lua
|
@ -1,55 +1,44 @@
|
|||||||
--- Join org
|
--- Adds a user to org
|
||||||
-- Adds initiator to an org
|
|
||||||
-- @module join_org
|
-- @module join_org
|
||||||
|
|
||||||
local join_org = {
|
join_org = {}
|
||||||
name = "Join this org",
|
|
||||||
|
join_org.setup = {
|
||||||
|
name = "Join Org",
|
||||||
slug = "join_org",
|
slug = "join_org",
|
||||||
desc = "Allows initiator to join this org"
|
desc = "If consent process is passed, initiator joins this org."
|
||||||
}
|
}
|
||||||
|
|
||||||
join_org.data = {
|
--- Adds the user to the org
|
||||||
result = nil
|
-- @function join_org.initiate
|
||||||
}
|
|
||||||
|
|
||||||
join_org.config = {
|
|
||||||
approval_module = false
|
|
||||||
}
|
|
||||||
|
|
||||||
--- Initiate join org with consent
|
|
||||||
-- @function join_org:initiate
|
|
||||||
-- @param result Callback if this module is embedded in other modules
|
-- @param result Callback if this module is embedded in other modules
|
||||||
function join_org:initiate(result)
|
function join_org.initiate(result)
|
||||||
if self.org:has_member(self.initiator) then
|
modpol.interactions.binary_poll_user(
|
||||||
modpol.interactions.message(
|
initiator,
|
||||||
self.initiator,
|
"Would you like to join " .. org.name,
|
||||||
"You are already a member of this org")
|
function (resp)
|
||||||
if result then result() end
|
if resp == "Yes" then
|
||||||
self.org:delete_process(self.id)
|
self.org:add_member(self.initiator)
|
||||||
else
|
end
|
||||||
self.data.result = result
|
end
|
||||||
self:call_module(
|
)
|
||||||
self.config.approval_module,
|
|
||||||
self.initiator,
|
for i, member in ipairs(self.org.members) do
|
||||||
{
|
self.org:add_pending_action(
|
||||||
prompt = "Allow " .. self.initiator .. " to join?"
|
member,
|
||||||
},
|
|
||||||
function ()
|
function ()
|
||||||
self:complete()
|
modpol.interactions.binary_poll_user(
|
||||||
|
member,
|
||||||
|
"Let " .. initiator .. " join " .. org.name .. "?",
|
||||||
|
function (resp)
|
||||||
|
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Adds member to org, notifies org, and deletes process
|
if result then result() end
|
||||||
-- @function join_org:complete
|
|
||||||
function join_org:complete()
|
|
||||||
self.org:add_member(self.initiator)
|
|
||||||
modpol.interactions.message_org(
|
|
||||||
self.initiator,self.org.name,
|
|
||||||
self.initiator .. " joined org " .. self.org.name)
|
|
||||||
if self.data.result then self.data.result() end
|
|
||||||
self.org:delete_process(self.id)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
modpol.modules.join_org = join_org
|
modpol.modules.join_org = join_org
|
||||||
|
57
modpol_core/modules/join_org_consent.lua
Normal file
57
modpol_core/modules/join_org_consent.lua
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
--- Join org (consent).
|
||||||
|
-- A simple module that calls a consent process on an org to add a member.
|
||||||
|
-- Depends on the Consent module.
|
||||||
|
-- @module join_org_consent
|
||||||
|
|
||||||
|
local join_org_consent = {
|
||||||
|
name = "Join this org (consent)",
|
||||||
|
slug = "join_org_consent",
|
||||||
|
desc = "Adds member with consent of all members"
|
||||||
|
}
|
||||||
|
|
||||||
|
join_org_consent.data = {
|
||||||
|
result = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
join_org_consent.config = {
|
||||||
|
}
|
||||||
|
|
||||||
|
--- Initiate join org with consent
|
||||||
|
-- @function join_org_consent:initiate
|
||||||
|
-- @param result Callback if this module is embedded in other modules
|
||||||
|
function join_org_consent:initiate(result)
|
||||||
|
if self.org:has_member(self.initiator) then
|
||||||
|
modpol.interactions.message(
|
||||||
|
self.initiator,
|
||||||
|
"You are already a member of this org")
|
||||||
|
if result then result() end
|
||||||
|
self.org:delete_process(self.id)
|
||||||
|
else
|
||||||
|
self.data.result = result
|
||||||
|
self:call_module(
|
||||||
|
"consent",
|
||||||
|
self.initiator,
|
||||||
|
{
|
||||||
|
prompt = "Allow " .. self.initiator .. " to join?",
|
||||||
|
votes_required = #self.org.members
|
||||||
|
},
|
||||||
|
function ()
|
||||||
|
self:complete()
|
||||||
|
end
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Adds member to org, notifies org, and deletes process
|
||||||
|
-- @function join_org_consent:complete
|
||||||
|
function join_org_consent:complete()
|
||||||
|
self.org:add_member(self.initiator)
|
||||||
|
modpol.interactions.message_org(
|
||||||
|
self.initiator,self.org.name,
|
||||||
|
"Consent reached: " .. self.initiator ..
|
||||||
|
" joined org " .. self.org.name)
|
||||||
|
if self.data.result then self.data.result() end
|
||||||
|
self.org:delete_process(self.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
modpol.modules.join_org_consent = join_org_consent
|
@ -1,26 +1,26 @@
|
|||||||
--- Remove child org
|
--- Remove child (consent).
|
||||||
-- A simple module that calls a process on an org to remove its child.
|
-- A simple module that calls a consent process on an org to remove its child.
|
||||||
-- @module remove_child_org
|
-- Depends on the Consent module.
|
||||||
|
-- @module remove_child_consent
|
||||||
|
|
||||||
local remove_child_org = {
|
local remove_child_consent = {
|
||||||
name = "Remove child org",
|
name = "Remove child (consent)",
|
||||||
slug = "remove_child_org",
|
slug = "remove_child_consent",
|
||||||
desc = "Removes a child org."
|
desc = "Removes a child org if all members of this org consent."
|
||||||
}
|
}
|
||||||
|
|
||||||
remove_child_org.data = {
|
remove_child_consent.data = {
|
||||||
result = nil,
|
result = nil,
|
||||||
child_to_remove = nil
|
child_to_remove = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
remove_child_org.config = {
|
remove_child_consent.config = {
|
||||||
approval_module = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Removes a child org with consent
|
--- Removes a child org with consent
|
||||||
-- @function remove_child_org:initiate
|
-- @function remove_child_consent:initiate
|
||||||
-- @param result Callback if this module is embedded in other modules
|
-- @param result Callback if this module is embedded in other modules
|
||||||
function remove_child_org:initiate(result)
|
function remove_child_consent:initiate(result)
|
||||||
local children = {}
|
local children = {}
|
||||||
for i,v in ipairs(self.org.children) do
|
for i,v in ipairs(self.org.children) do
|
||||||
local child = modpol.orgs.get_org(v)
|
local child = modpol.orgs.get_org(v)
|
||||||
@ -43,10 +43,11 @@ function remove_child_org:initiate(result)
|
|||||||
function(input)
|
function(input)
|
||||||
self.data.child_to_remove = modpol.orgs.get_org(input)
|
self.data.child_to_remove = modpol.orgs.get_org(input)
|
||||||
self:call_module(
|
self:call_module(
|
||||||
self.config.approval_module,
|
"consent",
|
||||||
self.initiator,
|
self.initiator,
|
||||||
{
|
{
|
||||||
prompt = "Remove child org "..input.."?"
|
prompt = "Remove child org "..input.."?",
|
||||||
|
votes_required = #self.org.members
|
||||||
},
|
},
|
||||||
function()
|
function()
|
||||||
self:complete()
|
self:complete()
|
||||||
@ -58,18 +59,19 @@ function remove_child_org:initiate(result)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Complete the remove process
|
--- Complete the remove process
|
||||||
-- @function remove_child_org:complete
|
-- @function remove_child_consent:complete
|
||||||
function remove_child_org:complete()
|
function remove_child_consent:complete()
|
||||||
modpol.interactions.message_org(
|
modpol.interactions.message_org(
|
||||||
self.initiator, self.data.child_to_remove.id,
|
self.initiator, self.data.child_to_remove.id,
|
||||||
"Removing this org: " .. self.data.child_to_remove.name)
|
"Removing org " .. self.data.child_to_remove.name ..
|
||||||
|
" by parent org consent")
|
||||||
modpol.interactions.message_org(
|
modpol.interactions.message_org(
|
||||||
self.initiator, self.org.id,
|
self.initiator, self.org.id,
|
||||||
"Removing child org of " .. self.org.name .. ": " ..
|
"Consent reached: removing org " ..
|
||||||
self.data.child_to_remove.name)
|
self.data.child_to_remove.name)
|
||||||
self.data.child_to_remove:delete()
|
self.data.child_to_remove:delete()
|
||||||
if self.data.result then self.data.result() end
|
if self.data.result then self.data.result() end
|
||||||
self.org:delete_process(self.id)
|
self.org:delete_process(self.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
modpol.modules.remove_child_org = remove_child_org
|
modpol.modules.remove_child_consent = remove_child_consent
|
@ -1,32 +1,29 @@
|
|||||||
--- Removes member from org
|
--- Calls consent to remove member from org
|
||||||
-- @module remove_member
|
-- @module remove_member_consent
|
||||||
|
|
||||||
local remove_member = {
|
local remove_member_consent = {
|
||||||
name = "Remove a member",
|
name = "Remove a member (consent)",
|
||||||
slug = "remove_member",
|
slug = "remove_member_consent",
|
||||||
desc = "Removes org member"
|
desc = "Removes org member with consent of other members"
|
||||||
}
|
}
|
||||||
|
|
||||||
remove_member.data = {
|
remove_member_consent.data = {
|
||||||
member_to_remove = "",
|
member_to_remove = "",
|
||||||
result = nil
|
result = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
remove_member.config = {
|
remove_member_consent.config = {
|
||||||
approval_module = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Removes given member from org
|
--- Removes given member from org
|
||||||
-- @function remove_member:initiate
|
-- @function remove_member_consent:initiate
|
||||||
-- @param result Callback if this module is embedded in other modules
|
-- @param result Callback if this module is embedded in other modules
|
||||||
function remove_member:initiate(result)
|
function remove_member_consent:initiate(result)
|
||||||
-- Abort if in root org
|
-- Abort if in root org
|
||||||
if self.org == modpol.instance then
|
if self.org == modpol.instance then
|
||||||
modpol.interactions.message(
|
modpol.interactions.message(
|
||||||
self.initiator,
|
self.initiator,
|
||||||
"Members cannot be removed from the root org")
|
"Members cannot be removed from the root org")
|
||||||
modpol.interactions.org_dashboard(
|
|
||||||
self.initiator, self.org.name)
|
|
||||||
if result then result() end
|
if result then result() end
|
||||||
self.org:delete_process(self.id)
|
self.org:delete_process(self.id)
|
||||||
else -- proceed if not root
|
else -- proceed if not root
|
||||||
@ -39,11 +36,12 @@ function remove_member:initiate(result)
|
|||||||
function(input)
|
function(input)
|
||||||
self.data.member_to_remove = input
|
self.data.member_to_remove = input
|
||||||
self:call_module(
|
self:call_module(
|
||||||
self.config.approval_module,
|
"consent",
|
||||||
self.initiator,
|
self.initiator,
|
||||||
{
|
{
|
||||||
prompt = "Remove "..input..
|
prompt = "Remove "..input..
|
||||||
" from org "..self.org.name.."?"
|
" from org "..self.org.name.."?",
|
||||||
|
votes_required = #self.org.members - 1
|
||||||
},
|
},
|
||||||
function()
|
function()
|
||||||
self:complete()
|
self:complete()
|
||||||
@ -55,11 +53,11 @@ function remove_member:initiate(result)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Complete after consent
|
--- Complete after consent
|
||||||
-- @function remove_member:complete
|
-- @function remove_member_consent:complete
|
||||||
function remove_member:complete()
|
function remove_member_consent:complete()
|
||||||
modpol.interactions.message_org(
|
modpol.interactions.message_org(
|
||||||
self.initiator, self.org.id,
|
self.initiator, self.org.id,
|
||||||
"Removing "..
|
"Consent reached: removing "..
|
||||||
self.data.member_to_remove..
|
self.data.member_to_remove..
|
||||||
" from org "..self.org.name)
|
" from org "..self.org.name)
|
||||||
self.org:remove_member(self.data.member_to_remove)
|
self.org:remove_member(self.data.member_to_remove)
|
||||||
@ -67,4 +65,4 @@ function remove_member:complete()
|
|||||||
if self.data.result then self.data.result() end
|
if self.data.result then self.data.result() end
|
||||||
end
|
end
|
||||||
|
|
||||||
modpol.modules.remove_member = remove_member
|
modpol.modules.remove_member_consent = remove_member_consent
|
@ -1,57 +1,32 @@
|
|||||||
--- Remove org
|
--- A simple module that removes an org.
|
||||||
-- Removes the current org
|
|
||||||
-- @module remove_org
|
-- @module remove_org
|
||||||
|
|
||||||
local remove_org = {
|
remove_org = {
|
||||||
name = "Remove this org",
|
name = "Remove this org",
|
||||||
slug = "remove_org",
|
slug = "remove_org",
|
||||||
desc = "Removes this org."
|
desc = "Eliminates the org and all child orgs."
|
||||||
}
|
}
|
||||||
|
|
||||||
remove_org.data = {
|
remove_org.config = {}
|
||||||
result = nil
|
remove_org.data = {}
|
||||||
}
|
|
||||||
|
|
||||||
remove_org.config = {
|
--- Removes org
|
||||||
approval_module = false
|
|
||||||
}
|
|
||||||
|
|
||||||
--- Remove org if all members consent
|
|
||||||
-- @function remove_org:initiate
|
-- @function remove_org:initiate
|
||||||
-- @param result Callback if this module is embedded in other modules
|
-- @param result Callback if this module is embedded in other modules
|
||||||
function remove_org:initiate(result)
|
function remove_org:initiate(result)
|
||||||
if self.org == modpol.instance then
|
if self.org == modpol.instance then
|
||||||
modpol.interactions.message(
|
modpol.interactions.message(
|
||||||
self.initiator,
|
self.initiator,
|
||||||
"Cannot remove root org")
|
"Cannot remove the root org")
|
||||||
if result then result() end
|
|
||||||
self.org:delete_process(self.id)
|
|
||||||
else
|
else
|
||||||
self.data.result = result
|
|
||||||
self:call_module(
|
|
||||||
self.config.approval_module,
|
|
||||||
self.initiator,
|
|
||||||
{
|
|
||||||
prompt = "Remove org " .. self.org.name .. "?"
|
|
||||||
},
|
|
||||||
function()
|
|
||||||
self:complete()
|
|
||||||
end
|
|
||||||
)
|
|
||||||
modpol.interactions.org_dashboard(
|
|
||||||
self.initiator, modpol.orgs.get_org(self.org.parent).name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Complete after approval
|
|
||||||
-- @function remove_org:complete
|
|
||||||
function remove_org:complete()
|
|
||||||
modpol.interactions.message_org(
|
modpol.interactions.message_org(
|
||||||
self.initiator,self.org.id,
|
self.initiator,self.org.id,
|
||||||
"Removing org " .. self.org.name)
|
"Removing org: "..self.org.name)
|
||||||
if self.data.result then self.data.result() end
|
|
||||||
self.org:delete_process(self.id)
|
|
||||||
self.org:delete()
|
self.org:delete()
|
||||||
|
modpol.interactions.dashboard(self.initiator)
|
||||||
|
-- call result function
|
||||||
|
end
|
||||||
|
if result then result() end
|
||||||
end
|
end
|
||||||
|
|
||||||
modpol.modules.remove_org = remove_org
|
modpol.modules.remove_org = remove_org
|
||||||
|
58
modpol_core/modules/remove_org_consent.lua
Normal file
58
modpol_core/modules/remove_org_consent.lua
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
--- Remove org (consent)
|
||||||
|
-- A simple module that calls a consent process on an org to remove it.
|
||||||
|
-- Depends on the Consent module.
|
||||||
|
-- @module remove_org_consent
|
||||||
|
|
||||||
|
local remove_org_consent = {
|
||||||
|
name = "Remove this org (consent)",
|
||||||
|
slug = "remove_org_consent",
|
||||||
|
desc = "Removes an org if all members consent."
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_org_consent.data = {
|
||||||
|
result = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_org_consent.config = {
|
||||||
|
}
|
||||||
|
|
||||||
|
--- Remove org if all members consent
|
||||||
|
-- @function remove_org_consent:initiate
|
||||||
|
-- @param result Callback if this module is embedded in other modules
|
||||||
|
function remove_org_consent:initiate(result)
|
||||||
|
if self.org == modpol.instance then
|
||||||
|
modpol.interactions.message(
|
||||||
|
self.initiator,
|
||||||
|
"Cannot remove root org")
|
||||||
|
if result then result() end
|
||||||
|
self.org:delete_process(self.id)
|
||||||
|
else
|
||||||
|
self.data.result = result
|
||||||
|
self:call_module(
|
||||||
|
"consent",
|
||||||
|
self.initiator,
|
||||||
|
{
|
||||||
|
prompt = "Remove org " .. self.org.name .. "?",
|
||||||
|
votes_required = #self.org.members
|
||||||
|
},
|
||||||
|
function()
|
||||||
|
self:complete()
|
||||||
|
end
|
||||||
|
)
|
||||||
|
modpol.interactions.org_dashboard(
|
||||||
|
self.initiator, self.org.name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Complete after consent
|
||||||
|
-- @function remove_org_consent:complete
|
||||||
|
function remove_org_consent:complete()
|
||||||
|
modpol.interactions.message_org(
|
||||||
|
self.initiator, self.org.id,
|
||||||
|
"Consent reached: removing org " .. self.org.name)
|
||||||
|
if self.data.result then self.data.result() end
|
||||||
|
self.org:delete_process(self.id)
|
||||||
|
self.org:delete()
|
||||||
|
end
|
||||||
|
|
||||||
|
modpol.modules.remove_org_consent = remove_org_consent
|
@ -4,7 +4,7 @@
|
|||||||
local remove_process = {
|
local remove_process = {
|
||||||
name = "Remove process",
|
name = "Remove process",
|
||||||
slug = "remove_process",
|
slug = "remove_process",
|
||||||
desc = "User can remove own processes, approval required for those of others",
|
desc = "User can remove own processes, consent required for those of others",
|
||||||
hide = false;
|
hide = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -12,7 +12,6 @@ remove_process.data = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
remove_process.config = {
|
remove_process.config = {
|
||||||
approval_module = "consent"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Initiate function
|
--- Initiate function
|
||||||
@ -72,12 +71,11 @@ function remove_process:initiate(result)
|
|||||||
self.org:delete_process(self.id)
|
self.org:delete_process(self.id)
|
||||||
else
|
else
|
||||||
self:call_module(
|
self:call_module(
|
||||||
self.config.approval_module,
|
"consent",
|
||||||
self.initiator,
|
self.initiator,
|
||||||
{
|
{
|
||||||
prompt =
|
prompt = "Approve removal of process "..process_choice.."?",
|
||||||
"Approve removal of process "
|
votes_required = #self.org.members
|
||||||
..process_choice.."?"
|
|
||||||
},
|
},
|
||||||
function(input)
|
function(input)
|
||||||
modpol.interactions.message_org(
|
modpol.interactions.message_org(
|
||||||
|
@ -1,26 +1,26 @@
|
|||||||
--- Rename org
|
--- Rename org (consent)
|
||||||
-- Calls a process on an org to rename it.
|
-- A simple module that calls a consent process on an org to rename it.
|
||||||
-- @module rename_org
|
-- Depends on the Consent module.
|
||||||
|
-- @module rename_org_consent
|
||||||
|
|
||||||
local rename_org = {
|
local rename_org_consent = {
|
||||||
name = "Rename this org",
|
name = "Rename this org (consent)",
|
||||||
slug = "rename_org",
|
slug = "rename_org_consent",
|
||||||
desc = "Renames an org."
|
desc = "Renames an org if all members consent."
|
||||||
}
|
}
|
||||||
|
|
||||||
rename_org.data = {
|
rename_org_consent.data = {
|
||||||
result = nil,
|
result = nil,
|
||||||
new_name = nil
|
new_name = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
rename_org.config = {
|
rename_org_consent.config = {
|
||||||
approval_module = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Renames the org after consent is reached
|
--- Renames the org after consent is reached
|
||||||
-- @function rename_org:initiate
|
-- @function rename_org_consent:initiate
|
||||||
-- @param result Callback if this module is embedded in other modules
|
-- @param result Callback if this module is embedded in other modules
|
||||||
function rename_org:initiate(result)
|
function rename_org_consent:initiate(result)
|
||||||
modpol.interactions.text_query(
|
modpol.interactions.text_query(
|
||||||
self.initiator,"New org name: ",
|
self.initiator,"New org name: ",
|
||||||
function(input)
|
function(input)
|
||||||
@ -50,11 +50,12 @@ function rename_org:initiate(result)
|
|||||||
self.org.name .. " to " .. input)
|
self.org.name .. " to " .. input)
|
||||||
-- initiate consent process
|
-- initiate consent process
|
||||||
self:call_module(
|
self:call_module(
|
||||||
self.config.approval_module,
|
"consent",
|
||||||
self.initiator,
|
self.initiator,
|
||||||
{
|
{
|
||||||
prompt = "Change name of org " ..
|
prompt = "Change name of org " ..
|
||||||
self.org.name .. " to " .. input .. "?"
|
self.org.name .. " to " .. input .. "?",
|
||||||
|
votes_required = #self.org.members
|
||||||
},
|
},
|
||||||
function()
|
function()
|
||||||
self:complete()
|
self:complete()
|
||||||
@ -66,9 +67,9 @@ function rename_org:initiate(result)
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Changes the name of the org
|
--- Changes the name of the org after consent is reached
|
||||||
-- @funciton rename_org
|
-- @funciton rename_org_consent
|
||||||
function rename_org:complete()
|
function rename_org_consent:complete()
|
||||||
modpol.interactions.message_org(
|
modpol.interactions.message_org(
|
||||||
self.initiator,
|
self.initiator,
|
||||||
self.org.name,
|
self.org.name,
|
||||||
@ -79,4 +80,4 @@ function rename_org:complete()
|
|||||||
self.org:delete_process(self.id)
|
self.org:delete_process(self.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
modpol.modules.rename_org = rename_org
|
modpol.modules.rename_org_consent = rename_org_consent
|
@ -16,7 +16,7 @@ send_token.data = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
send_token.config = {
|
send_token.config = {
|
||||||
token_name = nil -- hidden configuration
|
token_name = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
--- initiate function
|
--- initiate function
|
||||||
@ -29,7 +29,7 @@ function send_token:initiate(result)
|
|||||||
table.insert(token_list, k)
|
table.insert(token_list, k)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if #token_list == 0 then
|
if token_list == {} then
|
||||||
modpol.interactions.message(
|
modpol.interactions.message(
|
||||||
self.initiator,
|
self.initiator,
|
||||||
"No tokens in org")
|
"No tokens in org")
|
||||||
|
@ -26,12 +26,9 @@ module_template.data = {
|
|||||||
-- When calling a module from within another module,
|
-- When calling a module from within another module,
|
||||||
-- variables not defined in config will be ignored.
|
-- variables not defined in config will be ignored.
|
||||||
-- Default values set in config can be overridden
|
-- Default values set in config can be overridden
|
||||||
-- @field approval_module names a module that must pass before approval; defaults to false
|
|
||||||
-- @field field_1 ex: votes_required, default = 5
|
-- @field field_1 ex: votes_required, default = 5
|
||||||
-- @field field_2 ex: voting_type, default = "majority"
|
-- @field field_2 ex: voting_type, default = "majority"
|
||||||
module_template.config = {
|
module_template.config = {
|
||||||
approval_module = false -- visible but empty
|
|
||||||
hidden_config = nil -- not visible to users unless used
|
|
||||||
field_1 = 5
|
field_1 = 5
|
||||||
field_2 = "majority"
|
field_2 = "majority"
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
--- Tokenomics.
|
--- Tokenomics.
|
||||||
|
-- Depends on consent
|
||||||
-- @module tokenomics
|
-- @module tokenomics
|
||||||
|
|
||||||
local tokenomics = {
|
local tokenomics = {
|
||||||
@ -13,13 +14,14 @@ tokenomics.data = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
--- Config for module
|
--- Config for module
|
||||||
|
-- @field consent Require consent to create?
|
||||||
-- @field token_variables the data that goes into the token
|
-- @field token_variables the data that goes into the token
|
||||||
-- @field token_slug A no-spaces slug for the token
|
-- @field token_slug A no-spaces slug for the token
|
||||||
-- @field initial_treasury Quantity in org treasury
|
-- @field initial_treasury Quantity in org treasury
|
||||||
-- @field negative_spend Boolean: can users spend negative tokens? (for mutual credit)
|
-- @field negative_spend Boolean: can users spend negative tokens? (for mutual credit)
|
||||||
-- @field balances Table of user balances
|
-- @field balances Table of user balances
|
||||||
tokenomics.config = {
|
tokenomics.config = {
|
||||||
approval_module = false,
|
consent = false,
|
||||||
token_slug = "token",
|
token_slug = "token",
|
||||||
token_variables = {
|
token_variables = {
|
||||||
treasury = 0,
|
treasury = 0,
|
||||||
@ -41,24 +43,28 @@ function tokenomics:initiate(result)
|
|||||||
self.initiator, "Token slug taken, aborting")
|
self.initiator, "Token slug taken, aborting")
|
||||||
self.org:delete_process(self.id)
|
self.org:delete_process(self.id)
|
||||||
else
|
else
|
||||||
|
if self.config.consent then
|
||||||
self:call_module(
|
self:call_module(
|
||||||
self.config.approval_module,
|
"consent",
|
||||||
self.initiator,
|
self.initiator,
|
||||||
{
|
{
|
||||||
prompt = "Create token "..
|
prompt = "Create token "..
|
||||||
self.config.token_slug .. "?"
|
self.config.token_slug.."?",
|
||||||
|
votes_required = #self.org.members
|
||||||
},
|
},
|
||||||
function()
|
function()
|
||||||
modpol.interactions.message_org(
|
modpol.interactions.message_org(
|
||||||
self.initiator, self.org.id,
|
self.initiator, self.org.id,
|
||||||
"Creating token " ..
|
"Consent reached: creating token "..
|
||||||
self.config.token_slug)
|
self.config.token_slug)
|
||||||
self:create_token()
|
self:create_token()
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
|
else
|
||||||
|
self:create_token()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Create token
|
--- Create token
|
||||||
-- @function tokenomics:create_token
|
-- @function tokenomics:create_token
|
||||||
|
@ -25,24 +25,19 @@ end
|
|||||||
|
|
||||||
--- Return org when given its id or name
|
--- Return org when given its id or name
|
||||||
-- @function modpol.orgs.get_org
|
-- @function modpol.orgs.get_org
|
||||||
-- @param arg string for name of org or id of org, or nil if no org
|
-- @param arg string for name of org or id of org
|
||||||
-- @return org specified by id or name
|
-- @return org specified by id or name
|
||||||
function modpol.orgs.get_org(arg)
|
function modpol.orgs.get_org(arg)
|
||||||
local output = nil
|
|
||||||
if type(arg) == 'string' then
|
if type(arg) == 'string' then
|
||||||
for id, org in ipairs(modpol.orgs.array) do
|
for id, org in ipairs(modpol.orgs.array) do
|
||||||
if org ~= "deleted" then
|
|
||||||
if org.name == arg then
|
if org.name == arg then
|
||||||
output = org
|
return org
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif type(arg) == 'number' then
|
elseif type(arg) == 'number' then
|
||||||
if modpol.orgs.array[arg] ~= "deleted" then
|
return modpol.orgs.array[arg]
|
||||||
output = modpol.orgs.array[arg]
|
|
||||||
end
|
end
|
||||||
end
|
return nil
|
||||||
return output
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Return a table list of all org names
|
--- Return a table list of all org names
|
||||||
@ -85,7 +80,7 @@ function modpol.orgs.reset()
|
|||||||
modpol.util.copy_table(modpol.instance.members)
|
modpol.util.copy_table(modpol.instance.members)
|
||||||
for id, org in ipairs(modpol.orgs.array) do
|
for id, org in ipairs(modpol.orgs.array) do
|
||||||
if id > 1 then
|
if id > 1 then
|
||||||
modpol.orgs.array[id] = "deleted"
|
modpol.orgs.array[id] = "removed"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -220,17 +215,6 @@ function modpol.orgs:delete()
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
-- remove from parent's list
|
|
||||||
local parent = modpol.orgs.get_org(self.id)
|
|
||||||
if parent then
|
|
||||||
for k,v in ipairs(parent.children) do
|
|
||||||
if v == self.id then
|
|
||||||
v = "deleted"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- remove children
|
|
||||||
if #self.children > 0 then
|
if #self.children > 0 then
|
||||||
for i, child_id in pairs(self.children) do
|
for i, child_id in pairs(self.children) do
|
||||||
local child = modpol.orgs.get_org(child_id)
|
local child = modpol.orgs.get_org(child_id)
|
||||||
@ -239,8 +223,7 @@ function modpol.orgs:delete()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
modpol.orgs.array[self.id] = 'deleted'
|
modpol.orgs.array[self.id] = 'removed'
|
||||||
modpol.orgs.count = modpol.orgs.count - 1
|
|
||||||
modpol.ocutil.log('Deleted org ' .. self.name .. ': ' .. self.id)
|
modpol.ocutil.log('Deleted org ' .. self.name .. ': ' .. self.id)
|
||||||
|
|
||||||
self:record('Deleted ' .. self.name .. ' and all child orgs', 'del_org')
|
self:record('Deleted ' .. self.name .. ' and all child orgs', 'del_org')
|
||||||
|
@ -3,22 +3,13 @@
|
|||||||
|
|
||||||
--- Call modules
|
--- Call modules
|
||||||
-- @function modpol.orgs.call_module
|
-- @function modpol.orgs.call_module
|
||||||
-- @param module_slug Same as module name (or false to run result)
|
-- @param module_slug Same as module name
|
||||||
-- @param intiator Initiator for module
|
-- @param intiator Initiator for module
|
||||||
-- @param config Config for module
|
-- @param config Config for module
|
||||||
-- @param result
|
-- @param result
|
||||||
function modpol.orgs:call_module(module_slug, initiator, config, result, parent_id)
|
function modpol.orgs:call_module(module_slug, initiator, config, result, parent_id)
|
||||||
|
if not modpol.modules[module_slug] then
|
||||||
-- first, if no slug, just run result
|
modpol.ocutil.log('Error in ' .. self.name .. ':call_module -> module "' .. module_slug .. '" not found')
|
||||||
-- may not be necessary if we use false as default approval_module
|
|
||||||
if not module_slug then
|
|
||||||
if result() then
|
|
||||||
result()
|
|
||||||
end
|
|
||||||
return
|
|
||||||
-- if module doesn't exist, abort
|
|
||||||
elseif not modpol.modules[module_slug] then
|
|
||||||
modpol.ocutil.log('Error in ' .. self.name .. ':call_module -> module "' .. tostring(module_slug) .. '" not found')
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -73,8 +64,6 @@ function modpol.orgs:call_module(module_slug, initiator, config, result, parent_
|
|||||||
return index
|
return index
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- Get the root process of the given id
|
--- Get the root process of the given id
|
||||||
-- @function modpol.orgs.get_root_process
|
-- @function modpol.orgs.get_root_process
|
||||||
-- @param id
|
-- @param id
|
||||||
@ -87,7 +76,7 @@ function modpol.orgs:get_root_process(id)
|
|||||||
return process
|
return process
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Delete the process given id, return to dashboard
|
--- Delete the process given id
|
||||||
-- @function modpol.orgs.delete_process
|
-- @function modpol.orgs.delete_process
|
||||||
-- @param id
|
-- @param id
|
||||||
function modpol.orgs:delete_process(id)
|
function modpol.orgs:delete_process(id)
|
||||||
@ -108,7 +97,6 @@ function modpol.orgs:delete_process(id)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Delete process tree by id
|
--- Delete process tree by id
|
||||||
-- @function modpol.orgs:delete_process_tree
|
-- @function modpol.orgs:delete_process_tree
|
||||||
-- @param id Id of process tree
|
-- @param id Id of process tree
|
||||||
@ -134,7 +122,7 @@ end
|
|||||||
-- @param user
|
-- @param user
|
||||||
function modpol.orgs:remove_pending_action(process_id, user)
|
function modpol.orgs:remove_pending_action(process_id, user)
|
||||||
if self.pending[user] then
|
if self.pending[user] then
|
||||||
self.pending[user][process_id] = "deleted"
|
self.pending[user][process_id] = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -143,7 +131,7 @@ end
|
|||||||
-- @param process_id
|
-- @param process_id
|
||||||
function modpol.orgs:wipe_pending_actions(process_id)
|
function modpol.orgs:wipe_pending_actions(process_id)
|
||||||
for user in pairs(self.pending) do
|
for user in pairs(self.pending) do
|
||||||
self.pending[user][process_id] = "deleted"
|
self.pending[user][process_id] = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -165,7 +153,7 @@ function modpol.orgs:has_pending_actions(user)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Create user interaction with given process
|
--- Interact a user with given process
|
||||||
-- @function modpol.orgs:interact
|
-- @function modpol.orgs:interact
|
||||||
-- @param process_id
|
-- @param process_id
|
||||||
-- @param user
|
-- @param user
|
||||||
|
@ -11,6 +11,8 @@ modpol.file_ledger = modpol.datadir .. "/ledger.dat"
|
|||||||
modpol.file_orgs = modpol.datadir .. "/orgs.dat"
|
modpol.file_orgs = modpol.datadir .. "/orgs.dat"
|
||||||
modpol.file_old_ledgers = modpol.datadir .. "/old_ledgers.dat"
|
modpol.file_old_ledgers = modpol.datadir .. "/old_ledgers.dat"
|
||||||
|
|
||||||
|
os.execute ("mkdir -p " .. modpol.datadir)
|
||||||
|
|
||||||
modpol.ocutil.setlogdir (modpol.datadir)
|
modpol.ocutil.setlogdir (modpol.datadir)
|
||||||
modpol.ocutil.setlogname ("modpol.log")
|
modpol.ocutil.setlogname ("modpol.log")
|
||||||
|
|
||||||
@ -99,7 +101,7 @@ local load_orgs = function()
|
|||||||
-- setmetatable(org, modpol.orgs)
|
-- setmetatable(org, modpol.orgs)
|
||||||
-- end
|
-- end
|
||||||
|
|
||||||
local nn = modpol.orgs.count
|
local nn = modpol.ocutil.table_length (modpol.orgs.array)
|
||||||
local str = "entries"
|
local str = "entries"
|
||||||
if nn == 1 then str = "entry" end
|
if nn == 1 then str = "entry" end
|
||||||
modpol.ocutil.log (nn .. " orgs loaded from disk")
|
modpol.ocutil.log (nn .. " orgs loaded from disk")
|
||||||
|
23
modpol_core/storage/store-modules-legacy.lua
Normal file
23
modpol_core/storage/store-modules-legacy.lua
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
modpol.load_modules = function(path)
|
||||||
|
dofile (path .. "/add_child_org_consent.lua")
|
||||||
|
dofile (path .. "/add_child_org.lua")
|
||||||
|
dofile (path .. "/change_modules.lua")
|
||||||
|
dofile (path .. "/change_policy.lua")
|
||||||
|
dofile (path .. "/consent.lua")
|
||||||
|
dofile (path .. "/create_token.lua")
|
||||||
|
dofile (path .. "/defer_consent.lua")
|
||||||
|
dofile (path .. "/display_policies.lua")
|
||||||
|
dofile (path .. "/display_processes.lua")
|
||||||
|
dofile (path .. "/join_org_consent.lua")
|
||||||
|
dofile (path .. "/leave_org.lua")
|
||||||
|
dofile (path .. "/message_org.lua")
|
||||||
|
dofile (path .. "/randomizer.lua")
|
||||||
|
dofile (path .. "/remove_child_consent.lua")
|
||||||
|
dofile (path .. "/remove_member_consent.lua")
|
||||||
|
dofile (path .. "/remove_org_consent.lua")
|
||||||
|
dofile (path .. "/remove_org.lua")
|
||||||
|
dofile (path .. "/remove_process.lua")
|
||||||
|
dofile (path .. "/rename_org_consent.lua")
|
||||||
|
dofile (path .. "/send_token.lua")
|
||||||
|
dofile (path .. "/tokenomics.lua")
|
||||||
|
end
|
59
modpol_core/storage/store-modules.lua
Normal file
59
modpol_core/storage/store-modules.lua
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
local lfs
|
||||||
|
-- checks if lua file system is installed
|
||||||
|
local using_lfs = pcall(function() lfs = require "lfs" end)
|
||||||
|
|
||||||
|
-- switches to legacy module loading if lfs is not available
|
||||||
|
if using_lfs then
|
||||||
|
|
||||||
|
-- loads file names to ignore into a table
|
||||||
|
function fetch_ignores(module_path)
|
||||||
|
local ignore_list = {}
|
||||||
|
-- checks if ignore.txt exists
|
||||||
|
local f_test = io.open(module_path .. "/ignore.txt", "r")
|
||||||
|
if not f_test then return {} end
|
||||||
|
|
||||||
|
-- puts each line of ignore.txt into the table
|
||||||
|
local f = io.lines(module_path .. "/ignore.txt")
|
||||||
|
for line in f do
|
||||||
|
table.insert(ignore_list, line)
|
||||||
|
end
|
||||||
|
return ignore_list
|
||||||
|
end
|
||||||
|
|
||||||
|
-- checks if a string is in a list
|
||||||
|
function check_list(ignore_list, name)
|
||||||
|
for i, v in ipairs(ignore_list) do
|
||||||
|
if v == name then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
modpol.load_modules = function(module_path)
|
||||||
|
local loaded = 0
|
||||||
|
local ignored = 0
|
||||||
|
local ignores = fetch_ignores(module_path)
|
||||||
|
for file in lfs.dir(module_path) do
|
||||||
|
if file == "." or file == ".." then
|
||||||
|
-- ignoring current and parent directory
|
||||||
|
else
|
||||||
|
-- only looks for .lua files
|
||||||
|
if string.sub(file, -4, -1) == ".lua" then
|
||||||
|
|
||||||
|
-- doesn't load files in the ignore.txt
|
||||||
|
if check_list(ignores, file) then
|
||||||
|
ignored = ignored + 1
|
||||||
|
else
|
||||||
|
dofile(module_path .. "/" .. file)
|
||||||
|
loaded = loaded + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
print(loaded .. " modules loaded (" .. ignored .. " ignored)")
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
dofile (modpol.topdir .. "/storage/store-modules-legacy.lua")
|
||||||
|
end
|
109
modpol_core/storage/unix-storage.lua
Normal file
109
modpol_core/storage/unix-storage.lua
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
-- ===================================================================
|
||||||
|
-- /unix-storage.lua
|
||||||
|
-- Persistent storage in /data using Serpent Serializer
|
||||||
|
-- Unix systems only
|
||||||
|
|
||||||
|
modpol.datadir = modpol.topdir .. "/data"
|
||||||
|
modpol.file_ledger = modpol.datadir .. "/ledger.dat"
|
||||||
|
modpol.file_orgs = modpol.datadir .. "/orgs.dat"
|
||||||
|
|
||||||
|
os.execute ("mkdir -p " .. modpol.datadir)
|
||||||
|
|
||||||
|
modpol.ocutil.setlogdir (modpol.datadir)
|
||||||
|
modpol.ocutil.setlogname ("modpol.log")
|
||||||
|
|
||||||
|
modpol.serpent = {}
|
||||||
|
dofile (modpol.topdir .. "/util/serpent/serpent.lua")
|
||||||
|
|
||||||
|
-- ===================================================================
|
||||||
|
|
||||||
|
local write_file = function(path, data)
|
||||||
|
local file, err
|
||||||
|
file, err = io.open(path, "w")
|
||||||
|
if err then print(err) os.exit(1) end
|
||||||
|
file:write(data)
|
||||||
|
file:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
local read_file = function(path)
|
||||||
|
local file, err
|
||||||
|
file, err = io.open(path, "r")
|
||||||
|
if err then return nil end
|
||||||
|
local data = file:read()
|
||||||
|
file:close()
|
||||||
|
return data
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ===================================================================
|
||||||
|
|
||||||
|
local store_ledger = function(verbose)
|
||||||
|
local serialized_ledger = modpol.serpent.dump(modpol.ledger)
|
||||||
|
write_file(modpol.file_ledger, serialized_ledger)
|
||||||
|
|
||||||
|
local count = 0
|
||||||
|
for _ in pairs(modpol.ledger) do count = count + 1 end
|
||||||
|
|
||||||
|
if verbose then modpol.ocutil.log(count .. " ledger entries stored to disk")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local store_orgs = function(verbose)
|
||||||
|
local serialized_orgs = modpol.serpent.dump(modpol.orgs)
|
||||||
|
write_file(modpol.file_orgs, serialized_orgs)
|
||||||
|
|
||||||
|
local count = 0
|
||||||
|
for _ in pairs(modpol.orgs.array) do count = count + 1 end
|
||||||
|
|
||||||
|
if verbose then modpol.ocutil.log(count .. " orgs stored to disk")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
modpol.store_data = function(verbose)
|
||||||
|
store_ledger(verbose)
|
||||||
|
store_orgs(verbose)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ===================================================================
|
||||||
|
|
||||||
|
local load_ledger = function()
|
||||||
|
local obj = read_file(modpol.file_ledger)
|
||||||
|
if obj ~= nil then
|
||||||
|
local func, err = load(obj)
|
||||||
|
if err then
|
||||||
|
modpol.ocutil.log("Error loading ledger data")
|
||||||
|
os.exit(1)
|
||||||
|
end
|
||||||
|
modpol.ledger = func()
|
||||||
|
|
||||||
|
local count = 0
|
||||||
|
for _ in pairs(modpol.ledger) do count = count + 1 end
|
||||||
|
|
||||||
|
modpol.ocutil.log(count .. " ledger entries loaded from disk")
|
||||||
|
else
|
||||||
|
modpol.ocutil.log("No stored ledger data found")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local load_orgs = function()
|
||||||
|
local obj = read_file(modpol.file_orgs)
|
||||||
|
if obj ~= nil then
|
||||||
|
local func, err = load(obj)
|
||||||
|
if err then
|
||||||
|
modpol.ocutil.log("Error loading org data")
|
||||||
|
os.exit(1)
|
||||||
|
end
|
||||||
|
modpol.orgs = func()
|
||||||
|
|
||||||
|
local count = 0
|
||||||
|
for _ in pairs(modpol.orgs.array) do count = count + 1 end
|
||||||
|
|
||||||
|
modpol.ocutil.log(count .. " orgs loaded from disk")
|
||||||
|
else
|
||||||
|
modpol.ocutil.log("No stored orgs found")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
modpol.load_storage = function()
|
||||||
|
load_ledger()
|
||||||
|
load_orgs()
|
||||||
|
end
|
@ -32,13 +32,3 @@ function modpol.util.num_pairs(t)
|
|||||||
end
|
end
|
||||||
return i
|
return i
|
||||||
end
|
end
|
||||||
|
|
||||||
function modpol.util.lazy_table_length(tbl, lazy_val)
|
|
||||||
local count = 0
|
|
||||||
for k, v in ipairs(tbl) do
|
|
||||||
if v ~= lazy_val then
|
|
||||||
count = count + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return count
|
|
||||||
end
|
|
||||||
|
@ -1 +0,0 @@
|
|||||||
(placeholder)
|
|
@ -137,15 +137,11 @@ function modpol.interactions.org_dashboard(user, org_string)
|
|||||||
|
|
||||||
-- prepare children menu
|
-- prepare children menu
|
||||||
local children = {}
|
local children = {}
|
||||||
if org.children then
|
|
||||||
for k,v in ipairs(org.children) do
|
for k,v in ipairs(org.children) do
|
||||||
local this_child = modpol.orgs.get_org(v)
|
local this_child = modpol.orgs.get_org(v)
|
||||||
if this_child then
|
|
||||||
table.insert(children, this_child.name)
|
table.insert(children, this_child.name)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
table.sort(children)
|
table.sort(children)
|
||||||
end
|
|
||||||
|
|
||||||
-- prepare modules menu
|
-- prepare modules menu
|
||||||
local modules = {}
|
local modules = {}
|
||||||
|
Reference in New Issue
Block a user