|
|
(51 intermediate revisions by 4 users not shown) |
Line 1: |
Line 1: |
| <div class="article FileSha layout-2" id="FileSha"> | | <div class="article fileSHA_as_protocol layout-2" id="fileSHA_as_protocol"> |
|
| |
|
| [[File:Screenshot 2022-10-18 at 21.05.16.png|thumb|class=title_image|]]
| | <div class="hilight-h5"> |
|
| |
|
| === fileSHA as protocol=== | | <div class="hide-from-website"> |
| | [[File:Screenshot 2022-10-18 at 21.05.16.png|thumb|class=title_image scriptothek]] |
| | </div> |
|
| |
|
| <span class="author">André Fincato, Karl Moubarak</span> | | <div class="hide-from-book scriptothek"> |
| | [[File:Screenshot 2022-10-18 at 21.05.16.png|thumb|]] |
| | </div> |
|
| |
|
| | === fileSHA as protocol=== |
| | <span class="author">André Fincato and Karl Moubarak</span> |
| ==== Why fileSHA ==== | | ==== Why fileSHA ==== |
| | <code> |
| | !/bin/bash
|
|
| |
|
| #!/bin/bash
| | :init: remove existing data and initialize new game-session
<br> |
| | :create file to keep track of chosen members
<br> |
| | if [ ! -e ./.members ]; then
|
| | :touch ./.members
|
| |
else
|
| | :rm ./.members && touch ./.members
|
| | fi
|
|
| |
|
|
# init: remove existing data and initialize new game-session | | :create moderation folder where to move emails
<br> |
| | :from `<mlmmj>/<list>/moderation
<br> |
| | if [ ! -d ./moderation ]; then
|
| | :mkdir ./moderation
<br> |
| | else
|
| | :rm -rf ./moderation && mkdir ./moderation
<br> |
| | fi
<br> |
| | delete .game-over mark
<br>
|
| | rm -rf ./.game-over
<br> |
|
| |
|
|
# create file to keep track of chosen members
| | </code> |
| if [ ! -e ./.members ]; then
| |
| touch ./.members
| |
|
else
| |
| rm ./.members && touch ./.members
| |
| fi
| |
|
| |
|
| # create moderation folder where to move emails
| | <small>← Caption: init. instructions to kick-off the game.</small> |
| # from `<mlmmj>/<list>/moderation`
| |
| if [ ! -d ./moderation ]; then
| |
| mkdir ./moderation
| |
| else
| |
| rm -rf ./moderation && mkdir ./moderation
| |
| fi
| |
| | |
|
# delete .game-over mark
| |
| rm -rf ./.game-over
| |
| | |
| caption: init. instructions to kick-off the game.
| |
|
| |
|
|
| |
|
| ''fileSHA'' is an email, “turn-based” game that uses mailing list software as its main playground–think of a chat program but it's happening over an email exchange. You send a message to the list’s email address and the message is automatically distributed to everyone on the list. The core activity of the game is file sharing. A random participant receives a prompt via email to share a file however they want. The next randomly selected participant receives that file (sometimes by coordinating with the previous user) and then decides how to use it as an input source for the file they have chosen to share. At this point, no one else in the list knows what’s occurring except the two randomly chosen participants. | | ''fileSHA'' is an email, “turn-based” game that uses mailing list software as its main playground–think of a chat program but it's happening over an email exchange. You send a message to the list’s email address and the message is automatically distributed to everyone on the list. The core activity of the game is file sharing. A random participant receives a prompt via email to share a file however they want. The next randomly selected participant receives that file (sometimes by coordinating with the previous user) and then decides how to use it as an input source for the file they have chosen to share. At this point, no one else in the list knows what’s occurring except the two randomly chosen participants. |
|
| |
|
| | The project was born of our shared curiosity and fascination with mailing lists and the role they play in bringing communities together. We were guided by an all-too-common frustration that many will have related to in recent years, that is the sudden and abrupt disappearance of online spaces that were supposed to host communities, and especially the “data” produced by their users over time. Be that a group of people gathered around a shared love for a musical genre, a team collaborating on the development of a coding framework, or a discussion board on space exploration, it’s not uncommon to see communities hosted on Mastodon or Discord<ref>Another important example is a web service like Instagram (owned by Facebook / Meta) shutting down user profiles (also popular ones) due to “infringing the Terms and Conditions agreement” accepted by the user to the provider upon signing up to the website. This results in a real problem for most sex workers — including famous porn stars — who make use of the service to reach out to their public as well as to create connections with other workers.</ref> being closed unilaterally by their moderators, or having no way to export the “sociality” (collective memory) that’s being produced by users interaction into a data format that can be re-purposed or imported into another web service. This prompted us to ask the question: <br> |
| | ''What are other ways of communicating and navigating digital infrastructure that we might have overlooked or forgotten about?'' |
|
| |
|
| The project was born of our shared curiosity and fascination with mailing lists and the role they play in bringing communities together. We were guided by an all-too-common frustration that many will have related to in recent years, that is the sudden and abrupt disappearance of online spaces that were supposed to host communities, and especially the “data” produced by their users over time. Be that a group of people gathered around a shared love for a musical genre, a team collaborating on the development of a coding framework, or a discussion board on space exploration, it’s not uncommon to see communities hosted on Mastodon or Discord being closed unilaterally by their moderators, or having no way to export the “sociality” (collective memory) that’s being produced by users interaction into a data format that can be re-purposed or imported into another web service. This prompted us to ask the question: ''What are other ways of communicating and navigating digital infrastructure that we might have overlooked or forgotten about?''
| | Another inspiration for the game stems from André’s endless fascination for a piece of software called git. git propelled the Linux project<ref> Linux is a software project that launched in the early 1990s. It is the most widespread operating system used in web servers and among computer enthusiasts on “desktop.” From its conception, Linux has been entirely coordinated by sharing code through emails via the Internet.</ref> to become a viable, Internet-based, multiplayer effort. git uses emails as the main format for collaborating on a project, which means: mailing lists. |
| | |
| | |
| Another inspiration for the game stems from André’s endless fascination for a piece of software called git. git propelled the Linux project to become a viable, Internet-based, multiplayer effort. git uses emails as the main format for collaborating on a project, which means: mailing lists. | |
| | |
| | |
| Looking up examples of old mailing lists on the www we found, for instance, the cryptography archives. The mailing list dates back to 1970 (a Linux bug? There was no PGP software at the time, nor widespread email usage). Would an ongoing conversation thread be imaginable today, with the emergence of softwares such as Discord, an expressly community-oriented instant messaging platform? Does our frustration with online softwares have to do with these kinds of programs, or is to do with the composition and evolution of the HTTP protocol?
| |
|
| |
|
| | Looking up examples of old mailing lists on the www we found, for instance, the cryptography archives.<ref> The cryptography archives: https://www.metzdowd.com/pipermail/cryptography/.</ref> The mailing list dates back to 1970 (a Linux bug? There was no PGP software at the time, nor widespread email usage). Would an ongoing conversation thread be imaginable today, with the emergence of softwares such as Discord, an expressly community-oriented instant messaging platform? Does our frustration with online softwares have to do with these kinds of programs, or is to do with the composition and evolution of the HTTP protocol?<ref>HyperText Transfer Protocol is what is used to build websites and have them accessible over the Internet. If today we have broken links on the Web, is also due to specific choices taken, back in the early 1990s, when designing the way web pages should work.</ref> |
|
| |
|
| We dreamt of working with email protocols and mailing lists, instead of the web and the HTTP protocol. What’s the UI offered by a mailing list? How easy is it to join one? What types of interactions can be designed in this space and what “social etiquettes” can be established, stretched, or ignored? | | We dreamt of working with email protocols and mailing lists, instead of the web and the HTTP protocol. What’s the UI offered by a mailing list? How easy is it to join one? What types of interactions can be designed in this space and what “social etiquettes” can be established, stretched, or ignored? |
|
| |
|
| | | We decided to pick file sharing as the key activity in an email-based game as it aligns with another interest of ours: peer2peer computing<ref>Expressly: when two computers directly communicate with each other over the network without a third, usually “bigger” computer acting as intermediary. Classic example is file torrenting, but also LAN parties and self-hosted email servers are common examples.</ref>. Most p2p file-sharing software demands users to be online and at their computers at the same time, which adds an interesting requirement in the context of a non real-time technique like email: manual, human coordination. File sharing, to us, is an activity of making accessible files while simultaneously archiving them (by keeping a local copy of them on our computers). We are interested in exploring alternative methods and techniques to cloud-based file sharing or streaming software, where files continuously live online. As much as emails are easily copyable, shareable, and archivable, file sharing provides similar capabilities. |
| We decided to pick file sharing as the key activity in an email-based game as it aligns with another interest of ours: peer2peer computing. Most p2p file-sharing software demands users to be online and at their computers at the same time, which adds an interesting requirement in the context of a non real-time technique like email: manual, human coordination. File sharing, to us, is an activity of making accessible files while simultaneously archiving them (by keeping a local copy of them on our computers). We are interested in exploring alternative methods and techniques to cloud-based file sharing or streaming software, where files continuously live online. As much as emails are easily copyable, shareable, and archivable, file sharing provides similar capabilities. | |
| | |
|
| |
|
| ==== Protocol of the game ==== | | ==== Protocol of the game ==== |
Line 56: |
Line 57: |
| Here we have described the game in a protocolary format. While the game was originally played within email exchanges, we have tried to distill and extract most of the game’s components in such a way that it can also be played in a different format. | | Here we have described the game in a protocolary format. While the game was originally played within email exchanges, we have tried to distill and extract most of the game’s components in such a way that it can also be played in a different format. |
|
| |
|
| The original code repository with instructions can be accessed on the H&D Github page. | | ''The original code repository with instructions can be accessed on the H&D Github page.''<ref> https://github.com/hackersanddesigners/hd-filesha.</ref> |
| | |
| The game is chain-based. The more people that join, the better. Five to six players is the preferred minimum. | | The game is chain-based. The more people that join, the better. Five to six players is the preferred minimum. |
| fileSHA is an “exquisite-corpse” game, which means that the next player cannot see how the previous player altered the file being shared. A classic example of an exquisite corpse is a collective drawing game where the next player receives a sheet of paper folded by the previous person, so they cannot see what’s already been drawn on the sheet. | | fileSHA is an “exquisite-corpse” game, which means that the next player cannot see how the previous player altered the file being shared. A classic example of an exquisite corpse is a collective drawing game where the next player receives a sheet of paper folded by the previous person, so they cannot see what’s already been drawn on the sheet. |
|
| |
|
| |
|
| Furthermore we added two more elements: | | Furthermore we added two more elements: |
| | * Semi-randomness<ref> The game picks someone from the list of participants who has not already been chosen. Plus, in a computer system, “semi-randomness” is the only option anyway.</ref> of selecting the next player |
| | * “Secrecy” between the two players exchanging the outcome |
|
| |
|
| * Semi-randomness of selecting the next player
| | The object of the game is file sharing, meaning that each player receives the file(s) from the previous player and morphs it with one or more files of their choosing. Each player can decide how to use the previous file(s), for instance by compacting them into one file in the form of an archive (e.g., a ZIP file), or by deleting everything and sending a new, entirely different file. Nonetheless, the code we wrote keeps a record of what each participant shares, so that the process can still be revisited during and after the game finishes. So when we use the expression “file sharing technique”, we refer to the action of a player to decide how to share their file with the next player — for instance by attaching the file to the email, or using a p2p software — as well as by including a set of instructions in the email so that the next randomly chosen player can retrieve the file and keep the game going. |
| * “Secrecy” between the two players exchanging the outcome
| |
| | |
| | |
|
The object of the game is file sharing, meaning that each player receives the file(s) from the previous player and morphs it with one or more files of their choosing. Each player can decide how to use the previous file(s), for instance by compacting them into one file in the form of an archive (e.g., a ZIP file), or by deleting everything and sending a new, entirely different file. Nonetheless, the code we wrote keeps a record of what each participant shares, so that the process can still be revisited during and after the game finishes. So when we use the expression “file sharing technique”, we refer to the action of a player to decide how to share their file with the next player — for instance by attaching the file to the email, or using a p2p software — as well as by including a set of instructions in the email so that the next randomly chosen player can retrieve the file and keep the game going.
| |
| | |
| | |
| #!/bin/bash
| |
|
| |
|
| LIST=$1
| | <code> |
| | !/bin/bash
<br> |
|
| |
|
|
# TODO add check in case $LIST is empty string or not being passed
| | LIST=$1
<br> |
|
# save to variable list of address from specified mlmmj-list
| |
| # double trick:
| |
|
# the stdout result from the mlmmj command is flattened from a multiline print
| |
| # to a one line of values divided by empty space *when* saved to a variable
| |
|
# we can wrap this value directly inside an array `R=()`, and let bash array
| |
|
# to split the string by empty space
| |
|
| |
|
| ORIGINLIST=($(sudo /usr/bin/mlmmj-list -L /var/spool/mlmmj/$LIST))
| | :''TODO add check in case $LIST is empty string or not being passed'' |
| | :''save to variable list of address from specified mlmmj-list'' |
| | :''double trick:'' |
| | ::''the stdout result from the mlmmj command is flattened from a multiline print'' |
| | ::''to a one line of values divided by empty space *when* saved to a variable'' |
| | ::''we can wrap this value directly inside an array `R=()`, and let bash array'' |
| | ::''to split the string by empty space'' |
|
| |
|
| # loop over full member-list and create a new array with members
| | ORIGINLIST=($(sudo /usr/bin/mlmmj-list -L /var/spool/mlmmj/$LIST))
<br> |
|
# not found in ./members; those have been randomly chosen already
| |
| # fairly dumb approach but works fine
| |
|
| |
|
| CHOSEN=$(<./.members)
| | :''loop over full member-list and create a new array with members'' |
| | :''not found in ./members; those have been randomly chosen already'' |
| | :''fairly dumb approach but works fine'' |
|
| |
|
| LISTADDRESS=()
| | CHOSEN=$(<./.members)
<br> |
|
for member in "${ORIGINLIST[@]}"; do
| |
|
| |
|
| # check if current member is NOT present in $CHOSEN (use `!`)
| | LISTADDRESS=()<br> |
| # see <https://stackoverflow.com/a/231298>
| |
for member in "${ORIGINLIST[@]}"; do
|
| if [[ ! $CHOSEN =~ $member ]]; then
| |
| LISTADDRESS+=($member)
| |
| fi
| |
|
| |
|
|
done
| | :check if current member is NOT present in $CHOSEN (use `!`)
|
| | :see <https://stackoverflow.com/a/231298>
|
| | ::if [[ ! $CHOSEN =~ $member ]]; then
<br> |
| | :LISTADDRESS+=($member)
<br> |
| | :fi
<br> |
| |
:done
<br> |
|
| |
|
|
# pick a random member from the list
| | :''pick a random member from the list'' |
|
# and append it do .members
| | :''and append it do .members'' |
|
# -gt => greater than; see <https://askubuntu.com/a/1042664>
| | :''-gt => greater than; see <https://askubuntu.com/a/1042664>'' |
| SIZE=${#LISTADDRESS[@]}
| | :''SIZE=${#LISTADDRESS[@]}<br>'' |
|
| |
|
| if [ $SIZE -gt 0 ]; then
| | :if [ $SIZE -gt 0 ]; then
<br> |
| IDX=$((RANDOM % $SIZE))
| | :IDX=$((RANDOM % $SIZE))
<br> |
|
| |
|
| echo ${LISTADDRESS[$IDX]} >> ./.members
| | :echo ${LISTADDRESS[$IDX]} >> ./.members
<br> |
| echo ${LISTADDRESS[$IDX]}
| | :echo ${LISTADDRESS[$IDX]}
<br> |
| else
| | else
<br> |
| echo "$SIZE"
| | :echo "$SIZE"
<br> |
| fi
| | :fi
|
| | | </code> |
| caption: pick-random-address. instructions to pick the next random player from the subscription list.
| | <br> |
| | | <small>← Caption: pick-random-address. instructions to pick the next random player from the subscription list.</small> |
| | |
| We also specifically tried to come up with activities during the game that would introduce extra degrees of “complexity”. For instance, the game ticks at every seventy-two hours hours, and a new player is semi-randomly selected from the list. Sometimes a new player would be selected by choosing. Another example of adding complexity was to choose a file-sharing technique that required real-time coordination between participants (eg being online at the computer at the same time or through a certain period of time).
| |
|
| |
|
| | We also specifically tried to come up with activities during the game that would introduce extra degrees of “complexity”. For instance, the game ticks<ref> “A tick, also sometimes referred to as a jiffy, is a very small unit of time. A tick is used to determine the correct time and date on a computer.” (source https://www.computerhope.com/jargon/t/tick.htm). We use it as a verb instead of “ticking”.</ref> at every seventy-two hours hours, and a new player is semi-randomly selected from the list. Sometimes a new player would be selected by choosing. Another example of adding complexity was to choose a file-sharing technique that required real-time coordination between participants (e.g. being online at the computer at the same time or through a certain period of time). |
|
| |
|
| The two technologies that we chose for the game are partly or completely asynchronous (file sharing and emails), which helps to create friction within its linear-time framework (e.g., that the game is chain-based and moves from one player to the next). | | The two technologies that we chose for the game are partly or completely asynchronous (file sharing and emails), which helps to create friction within its linear-time framework (e.g., that the game is chain-based and moves from one player to the next). |
|
| |
|
| |
|
| These are the rules of the game: | | These are the rules of the game: |
|
| |
|
| * Set up the game so that people who are interested in playing can join
| | ===== Set up the game so that people who are interested in playing can join ===== |
|
| |
|
| In our case, the list remained open while the game was in play, meaning that someone could join mid-game and extend its duration by being semi-randomly chosen to be one of the next participants. | | In our case, the list remained open while the game was in play, meaning that someone could join mid-game and extend its duration by being semi-randomly chosen to be one of the next participants. |
|
| |
|
| * Set up a system to randomly pick the next player
| | ===== Set up a system to randomly pick the next player ===== |
|
| |
|
| We did this using computer software with a semi-random function (see the code snippet above the caption pick-random-address). Further rules can be added, for instance whether a participant joins early or later on in the process. | | We did this using computer software with a semi-random function (see the code snippet above the caption pick-random-address). Further rules can be added, for instance whether a participant joins early or later on in the process. |
|
| |
|
| * Set up a timer and game duration
| | ===== Set up a timer and game duration ===== |
|
| |
|
| We opted for seventy-two hours in a software asynchronous setting, which turned out to be too little time for the player to perform their tasks, these being: receive the file; add, remove and/or extend it; pick a file sharing method; share it with the next player. | | We opted for seventy-two hours in a software asynchronous setting, which turned out to be too little time for the player to perform their tasks, these being: receive the file; add, remove and/or extend it; pick a file sharing method; share it with the next player. |
|
| |
|
| * Pick a way for the two selected players to exchange information privately
| | ===== Pick a way for the two selected players to exchange information privately ===== |
|
| |
|
| We did not use the main benefit of using mailing list software, which is to send to everyone in the list the same message. We also exploited email software by re-writing the email address of the new sender before manually sending the email to the next randomly chosen player, therefore breaking continuity. | | We did not use the main benefit of using mailing list software, which is to send to everyone in the list the same message. We also exploited email software by re-writing the email address of the new sender before manually sending the email to the next randomly chosen player, therefore breaking continuity. |
|
| |
|
| * Choose an exchange activity to complete during the game
| | ===== Choose an exchange activity to complete during the game ===== |
|
| |
|
| The fact that file sharing can be interpreted quite widely contributed to unforeseen elements, which we thought could improve the overall strict linear-time experience (e.g., by having to deal with human-coordination between players, disk-space availability, etc). | | The fact that file sharing can be interpreted quite widely contributed to unforeseen elements, which we thought could improve the overall strict linear-time experience (e.g., by having to deal with human-coordination between players, disk-space availability, etc.). |
|
| |
|
| * Kick off the game as the host
| | ===== Kick off the game as the host ===== |
|
| |
|
| Start the chain of “exchange-activity” by setting an interesting example, e.g., pick a file and a method of sharing it that stirs up engagement. | | Start the chain of “exchange-activity” by setting an interesting example, e.g., pick a file and a method of sharing it that stirs up engagement. |
|
| |
|
| * Send updates to participants
| | ===== Send updates to participants ===== |
|
| |
|
| If the time interval is longer than a few hours of gameplay, it might be a good idea to keep participants posted about what is going on while they are not actively playing. Of course, if the game takes place in one room, then this is probably not necessary. | | If the time interval is longer than a few hours of gameplay, it might be a good idea to keep participants posted about what is going on while they are not actively playing. Of course, if the game takes place in one room, then this is probably not necessary. |
|
| |
|
| * Provide ways to ask for “help“ or to access the rules of the game at any time
| | ===== Provide ways to ask for “help“ or to access the rules of the game at any time ===== |
|
| |
|
| One happy, unintended effect of using a mailing list software was the ability to use the feature of asking for “help/info” about the list: e.g., how to unsubscribe, or how to access previous messages. We used the info text to provide the basic rules of the game, and made status updates on which files had been shared so far. The “help” screen of a video game was the main source of inspiration for this feature. | | One happy, unintended effect of using a mailing list software was the ability to use the feature of asking for “help/info” about the list: e.g., how to unsubscribe, or how to access previous messages. We used the info text to provide the basic rules of the game, and made status updates on which files had been shared so far. The “help” screen of a video game was the main source of inspiration for this feature. |
|
| |
|
| #!/bin/bash
| | <code> |
| LIST_PATH=$1
| | !/bin/bash
<br> |
| LIST_NAME=$(basename $LIST_PATH)
| |
|
| |
|
| LIST_SENDER=$(<./.list-sender)
| | LIST_PATH=$1
<br> |
| LIST_PREFIX=$(<$LIST_PATH/control/prefix)
| | LIST_NAME=$(basename $LIST_PATH)
<br> |
|
| |
|
| # read moderator email list from file and break multiline text into one line
| | LIST_SENDER=$(<./.list-sender)
<br> |
|
# (this is how `mailx` receives multiple recipients
| | LIST_PREFIX=$(<$LIST_PATH/control/prefix)
|
| | :''read moderator email list from file and break multiline text into one line'' |
| | :''(this is how `mailx` receives multiple recipients'' |
| MODERATORS=$(tr '\n' ' ' < "$LIST_PATH/control/owner") | | MODERATORS=$(tr '\n' ' ' < "$LIST_PATH/control/owner") |
|
| |
|
|
GAME_OVER="game over! all subscribers have been chosen as list contributors!
| | :''GAME_OVER="game over! all subscribers have been chosen as list contributors!'' |
| "
ERROR_CHAIN="An error happened; the chain order broke probably due to a mismatch in the .member list; please check!" | | :''"ERROR_CHAIN="An error happened; the chain order broke probably due to a mismatch in the .member list; please check!"'' |
|
ERROR_NOPOST="No email has been received yet, run parse-email after a message has been posted to the list"
| | :''ERROR_NOPOST="No email has been received yet, run parse-email after a message has been posted to the list"'' |
|
| |
|
|
# check if there's any email held in /moderation
| | :''check if there's any email held in /moderation'' |
|
# we could check if $EMAIL_FN is an empty string
| | :''we could check if $EMAIL_FN is an empty string'' |
| # but it seems like eagerly asking for more troubles
| | :''but it seems like eagerly asking for more troubles'' |
| MOD_N=$(ls "$LIST_PATH/moderation" | wc -l) | | MOD_N=$(ls "$LIST_PATH/moderation" | wc -l) |
|
| |
|
|
if [ "$MOD_N" == "0" ]; then
| |
if [ "$MOD_N" == "0" ]; then<br> |
|
| |
|
| echo "no email held in moderation, checking subscribers list..."
| | :echo "no email held in moderation, checking subscribers list..."
<br> |
| CHOSEN_SIZE=$(./check-member $LIST_NAME)
| | :CHOSEN_SIZE=$(./check-member $LIST_NAME)<br> |
|
| |
|
| if [ "$CHOSEN_SIZE" == "0" ]; then
| | if [ "$CHOSEN_SIZE" == "0" ]; then<br> |
| # check if game-over email was sent already
| |
| if [ -e ./.game-over ]; then
| |
|
| |
|
| exit 1
| | :''check if game-over email was sent already'' |
| | :if [ -e ./.game-over ]; then<br> |
|
| |
|
| else
| | exit 1
<br> |
|
| |
|
| touch ./.game-over
| | :else<br> |
|
| |
|
| echo "$GAME_OVER"
| | touch ./.game-over
<br> |
| echo "$GAME_OVER" | mailx -a "From: $LIST_SENDER" -s "$LIST_PREFIX Game Over"
| |
| $MODERATORS
| |
|
| |
|
| fi
| | echo "$GAME_OVER"<br> |
| | :echo "$GAME_OVER" | mailx -a "From: $LIST_SENDER" -s "$LIST_PREFIX Game Over"<br> |
| | $MODERATORS<br> |
|
| |
|
| else
| | :fi<br> |
| # something might have happen, eg contributor did not send email within
| |
| # x-time, or other things...
| |
| # move on with the next contributor, if any is left
| |
| # check latest email received, which we moved to ./moderation/
| |
| # send message to next chosen contributor, and pray the gods
| |
|
| |
|
| EMAIL_FN=$(ls -t "./moderation" | head -n1)
| | else
<br> |
| if [ -z "$EMAIL_FN" ]; then
| | :''something might have happen, eg contributor did not send email within'' |
| | :''x-time, or other things...'' |
| | :''move on with the next contributor, if any is left'' |
| | :''check latest email received, which we moved to ./moderation/'' |
| | :''send message to next chosen contributor, and pray the gods'' |
|
| |
|
| echo "$ERROR_NOPOST"
| | EMAIL_FN=$(ls -t "./moderation" | head -n1)
<br> |
| echo "$ERROR_NOPOST" | mailx -a "From: $LIST_SENDER" -s "$LIST_PREFIX Error: no post" $MODERATORS
| | if [ -z "$EMAIL_FN" ]; then
<br> |
|
| |
|
| exit 1
| | :echo "$ERROR_NOPOST"<br> |
| | :echo "$ERROR_NOPOST" | mailx -a "From: $LIST_SENDER" -s "$LIST_PREFIX Error: no post" $MODERATORS
<br> |
|
| |
|
| else
| | exit 1
<br> |
| EMAIL_PATH="./moderation/$EMAIL_FN"
| |
|
| |
|
| MEMBERS_LAST=$(tail -n1 .members)
| | else
<br> |
| | :EMAIL_PATH="./moderation/$EMAIL_FN"
<br> |
| | :MEMBERS_LAST=$(tail -n1 .members)
<br> |
|
| |
|
| # pick next contributor
| | :''pick next contributor'' |
| CONTRIBUTOR_NEXT=$(./pick-random-address $LIST_NAME)
| | CONTRIBUTOR_NEXT=$(./pick-random-address $LIST_NAME)
<br>
|
| echo "Next contributor (1) => $CONTRIBUTOR_NEXT"
| | echo "Next contributor (1) => $CONTRIBUTOR_NEXT"
<br>
|
|
| |
|
| # `-o` is the OR operator
| | :''`-o` is the OR operator''
<br> |
| if [ "$CHOSEN_SIZE" == "0" -o -z "$CONTRIBUTOR_NEXT" ]; then
| | if [ "$CHOSEN_SIZE" == "0" -o -z "$CONTRIBUTOR_NEXT" ]; then
<br> |
| echo "$ERROR_CHAIN"
| | echo "$ERROR_CHAIN"
<br> |
|
| |
|
| # send email error
| | :''send email error'' |
| echo "$ERROR_CHAIN" | mailx -a "From: $LIST_SENDER" -s "$LIST_PREFIX Error" | | echo "$ERROR_CHAIN" | mailx -a "From: $LIST_SENDER" -s "$LIST_PREFIX Error"
<br> |
|
| |
|
| $MODERATORS
| | $MODERATORS
<br> |
|
| |
|
| else
| | :else
<br> |
|
| |
|
| # replace `To:` address
| | :''replace `To:` address''<br> |
| sed -i "s/^To: .*$/To: $CONTRIBUTOR_NEXT/" $EMAIL_PATH
| | :sed -i "s/^To: .*$/To: $CONTRIBUTOR_NEXT/" $EMAIL_PATH
<br> |
|
| |
|
| # and send email to this address
| | :''and send email to this address'' |
| /usr/sbin/sendmail -t $CONTRIBUTOR_NEXT < $EMAIL_PATH
| | :/usr/sbin/sendmail -t $CONTRIBUTOR_NEXT < $EMAIL_PATH
<br> |
|
| |
|
| fi
| | :fi
|
| fi
| | fi<br>
|
| fi | | fi<br> |
|
| |
|
|
else
| |
else
|
| # at least one message is present in `<mlmmj>/<list>/moderation`
| | :''at least one message is present in `<mlmmj>/<list>/moderation`''
<br> |
|
| |
|
| # fetch latest submitted email filename
| | :''fetch latest submitted email filename'' |
| # <https://stackoverflow.com/a/1015687>
| | :''<https://stackoverflow.com/a/1015687>'' |
| EMAIL_FN=$(ls -t "$LIST_PATH/moderation" | head -n1)
| | EMAIL_FN=$(ls -t "$LIST_PATH/moderation" | head -n1)<br> |
| EMAIL_PATH="$LIST_PATH/moderation/$EMAIL_FN"
| | EMAIL_PATH="$LIST_PATH/moderation/$EMAIL_FN"
<br> |
|
| |
|
| MEMBERS_LAST=$(tail -n1 .members)
| | MEMBERS_LAST=$(tail -n1 .members)
<br> |
| FROM=$(sed -n 's/^From:.*<\(.*\)>$/\1/p' $EMAIL_PATH)
| | FROM=$(sed -n 's/^From:.*<\(.*\)>$/\1/p' $EMAIL_PATH)
<br> |
|
| |
|
| SENDER=$(<"$LIST_PATH/control/listaddress")
| | SENDER=$(<"$LIST_PATH/control/listaddress")
<br> |
|
| |
|
| # check if $MEMBERS_LAST is empty string (eg no contributor has been chosen yet)
| | :''check if $MEMBERS_LAST is empty string (eg no contributor has been chosen yet)'' |
| if [ -z "$MEMBERS_LAST" ]; then
| | if [ -z "$MEMBERS_LAST" ]; then
<br> |
|
| |
|
| # check if it is the first message in the chain
| | :''check if it is the first message in the chain'' |
| # by checking list of chosen members
| | by checking list of chosen members
<br> |
|
| |
|
| CHOSEN=$(<./.members)
| | :CHOSEN=$(<./.members)
<br> |
| CHOSEN_SIZE=${#CHOSEN[@]}
| | :CHOSEN_SIZE=${#CHOSEN[@]}
<br> |
|
| |
|
| echo "CHOSEN => $CHOSEN"
| | echo "CHOSEN => $CHOSEN"<br> |
| echo "CHOSEN_SIZE => $CHOSEN_SIZE"
| | echo "CHOSEN_SIZE => $CHOSEN_SIZE"
<br> |
|
| |
|
| # check if list of chosen members equals to 1
| | :''check if list of chosen members equals to 1'' |
| if [ $CHOSEN_SIZE -eq 1 ]; then
| | if [ $CHOSEN_SIZE -eq 1 ]; then
<br> |
|
| |
|
| # mv file out of /moderation to current dir
| | :''mv file out of /moderation to current dir'' |
| mv $EMAIL_PATH ./moderation/.
| | mv $EMAIL_PATH ./moderation/.<br> |
|
| |
|
| # add address from first received email to chosen list
| | :''add address from first received email to chosen list'' |
| echo "$FROM" >> ./.members
| | :echo "$FROM" >> ./.members<br> |
|
| |
|
| # update list of file-sharing methods shared so far
| | :''update list of file-sharing methods shared so far'' |
| ./get-subject-line $LIST_PATH
| | ./get-subject-line $LIST_PATH
<br> |
|
| |
|
| # pick next contributor
| | :''pick next contributor'' |
| CONTRIBUTOR_NEXT=$(./pick-random-address $LIST_NAME)
| | :CONTRIBUTOR_NEXT=$(./pick-random-address $LIST_NAME)
<br> |
| echo "Next contributor (2) => $CONTRIBUTOR_NEXT"
| | echo "Next contributor (2) => $CONTRIBUTOR_NEXT"
|
|
| |
|
| # replace `From:` and `To:` addresses
| | :''replace `From:` and `To:` addresses'' |
| sed -i "s/^From: .*$/From: <$SENDER>/" "./moderation/$EMAIL_FN"
| | :sed -i "s/^From: .*$/From: <$SENDER>/" "./moderation/$EMAIL_FN"
<br> |
| sed -i "s/^To: .*$/To: $CONTRIBUTOR_NEXT/" "./moderation/$EMAIL_FN"
| | :sed -i "s/^To: .*$/To: $CONTRIBUTOR_NEXT/" "./moderation/$EMAIL_FN"
<br> |
|
| |
|
| # and send email to this address
| | :''and send email to this address'' |
| /usr/sbin/sendmail -t $CONTRIBUTOR_NEXT < "./moderation/$EMAIL_FN"
| | :/usr/sbin/sendmail -t $CONTRIBUTOR_NEXT < "./moderation/$EMAIL_FN"<br> |
|
| |
|
| else
| | else<br> |
|
| |
|
| echo "something went particularly wrong, exit"
| | :echo "something went particularly wrong, exit"<br> |
| exit 1
| | :exit 1
<br> |
| fi
| | fi
|
|
| |
|
| elif [ "$MEMBERS_LAST" == "$FROM" ]; then
| | elif [ "$MEMBERS_LAST" == "$FROM" ]; then
|
|
| |
|
| # pick next contributor
| | :''pick next contributor'' |
| CONTRIBUTOR_NEXT=$(./pick-random-address $LIST_NAME)
| | CONTRIBUTOR_NEXT=$(./pick-random-address $LIST_NAME)<br> |
|
| |
|
| # `-o` is the OR operator
| | :''`-o` is the OR operator'' |
| if [ -z "$CONTRIBUTOR_NEXT" ]; then
| | if [ -z "$CONTRIBUTOR_NEXT" ]; then
|
| echo "An error happened; the chain order broke probably due to a mismatch in the .member list; please check!"
| | :echo "An error happened; the chain order broke probably due to a mismatch in the .member list; please check!"
<br> |
| | |
| elif [ "$CONTRIBUTOR_NEXT" == "0" ]; then
| |
|
| |
|
| # check if game-over email was sent already
| | :elif [ "$CONTRIBUTOR_NEXT" == "0" ]; then
<br> |
|
| |
|
| if [ -e ./.game-over ]; then
| | ''check if game-over email was sent already'' |
| | :if [ -e ./.game-over ]; then
<br> |
|
| |
|
| exit 1
| | exit 1
<br> |
|
| |
|
| else
| | :else
<br> |
|
| |
|
| touch ./.game-over
| | touch ./.game-over
<br> |
|
| |
|
| echo "$GAME_OVER"
| | echo "$GAME_OVER"
|
|
| |
|
| echo "$GAME_OVER" | mailx -a "From: $LIST_SENDER" -s "$LIST_PREFIX Game | | :echo "$GAME_OVER" | mailx -a "From: $LIST_SENDER" -s "$LIST_PREFIX Game<br> |
|
| |
|
| Over" $MODERATORS
| | Over" $MODERATORS
<br> |
| | | |
| fi
| | :fi
<br> |
| | |
| else
| |
| | |
| echo "Next contributor (3) => $CONTRIBUTOR_NEXT"
| |
| | |
| | |
| # mv file out of /moderation to current dir
| |
| | |
| mv $EMAIL_PATH ./moderation/.
| |
|
| |
|
| | else
<br> |
|
| |
|
| # update list of file-sharing methods shared so far
| | :echo "Next contributor (3) => $CONTRIBUTOR_NEXT"<br> |
|
| |
|
| ./get-subject-line $LIST_PATH
| | :mv file out of /moderation to current dir
<br> |
| | mv $EMAIL_PATH ./moderation/.
<br> |
|
| |
|
| | :update list of file-sharing methods shared so far
<br> |
| | ./get-subject-line $LIST_PATH
<br> |
|
| |
|
| # replace `From:` and `To:` addresses
| | :''replace `From:` and `To:` addresses''
<br> |
| | :sed -i "s/^From: .*$/From: <$SENDER>/" "./moderation/$EMAIL_FN"<br> |
| | :sed -i "s/^To: .*$/To: $CONTRIBUTOR_NEXT/" "./moderation/$EMAIL_FN"<br> |
|
| |
|
| sed -i "s/^From: .*$/From: <$SENDER>/" "./moderation/$EMAIL_FN"
| | :''and send email to this address''
<br> |
| | |
| sed -i "s/^To: .*$/To: $CONTRIBUTOR_NEXT/" "./moderation/$EMAIL_FN"
| |
| | |
| # and send email to this address
| |
|
| |
| /usr/sbin/sendmail -t $CONTRIBUTOR_NEXT < "./moderation/$EMAIL_FN"
| | /usr/sbin/sendmail -t $CONTRIBUTOR_NEXT < "./moderation/$EMAIL_FN"
|
|
| |
|
| | :fi
<br> |
|
| |
|
| fi
| | else
<br> |
| | | :ERROR_MISMATCH="$MEMBERS_LAST differs from $FROM. This means the user who sent the email does not match with the latest email being added to .members."
<br> |
| else
| | :echo "$ERROR_MISMATCH"
<br> |
| | |
| ERROR_MISMATCH="$MEMBERS_LAST differs from $FROM. This means the user who sent the email does not match with the latest email being added to .members."
| |
| | |
| echo "$ERROR_MISMATCH"
echo "$ERROR_MISMATCH" | mailx -a "From: $LIST_SENDER" -s "$LIST_PREFIX Error" | |
|
| |
|
| | echo "$ERROR_MISMATCH" | mailx -a "From: $LIST_SENDER" -s "$LIST_PREFIX Error"<br> |
| $MODERATORS
| | $MODERATORS
|
|
| |
|
| | :fi<br> |
|
| |
|
| fi
| |
fi<br> |
| | | </code> |
|
fi | | <br> |
| | | <small>← Caption: parse-email. instructions to read an incoming email held in moderation.</small> |
| | |
| ''Caption: parse-email. instructions to read an incoming email held in moderation.
''
| |
|
| |
|
| ==== Closing ==== | | ==== Closing ==== |
|
| |
| We finish with a closing remark on the often critiqued set of hydraulic metaphors—for instance: “pull,” “drain,” “consume,” “push,” “dump” a stream (of data), all the way to the extreme of “the cloud,”—which is used in computer programming by “engineers”, to talk about software that recontextualizes the domain specific language: | | We finish with a closing remark on the often critiqued set of hydraulic metaphors—for instance: “pull,” “drain,” “consume,” “push,” “dump” a stream (of data), all the way to the extreme of “the cloud,”—which is used in computer programming by “engineers”, to talk about software that recontextualizes the domain specific language: |
|
| |
|
| | <blockquote>“Geologists have uncovered one such mechanism: rivers acting as veritable hydraulic computers (or at least, sorting machines). Rivers transport rocky materials from their point of origin (a previously created mountain subject to erosion or weathering) to the place in the ocean where these materials will accumulate. In this process, pebbles of variable size, weight and shape tend to react differently to the water transporting them. […] Once the raw materials have been sorted out into more or less homogenous groupings deposited at the bottom of the sea (that is, once they have become sedimented), a second operation is necessary to transform these loose collections of pebbles into an entity of a higher scale: a sedimentary rock. This operation consists in cementing the sorted components together into a new entity with emergent properties of its own, that is, properties such as overall strength and permeability that cannot be ascribed to the sum of the individual pebbles.”<ref> Manuel De Landa, “The Geology Of Morals: A Neo-Materialist Interpretation,” WORLD INFORMATION INSTITUTE, http://www.t0.or.at/delanda/geology.htm</ref></blockquote> |
|
| |
|
| <blockquote>
| | Designing fileSHA with mailing list software gave us the space to explore the process of file sharing. Furthermore, we realized that this game has the potential to be played for an infinite amount of time. Software architectures like those of a mailing list allow for “necroposting,” We believe there is no shame in resurrecting conversations that are six months or ten years old, because at best it’s experienced as a collective sedimentation process that belongs as much to you as it does to those who wrote about it months to a decade earlier. Computers as rivers! |
| “Geologists have uncovered one such mechanism: rivers acting as veritable hydraulic computers (or at least, sorting machines). Rivers transport rocky materials from their point of origin (a previously created mountain subject to erosion or weathering) to the place in the ocean where these materials will accumulate. In this process, pebbles of variable size, weight and shape tend to react differently to the water transporting them. […] Once the raw materials have been sorted out into more or less homogenous groupings deposited at the bottom of the sea (that is, once they have become sedimented), a second operation is necessary to transform these loose collections of pebbles into an entity of a higher scale: a sedimentary rock. This operation consists in cementing the sorted components together into a new entity with emergent properties of its own, that is, properties such as overall strength and permeability that cannot be ascribed to the sum of the individual pebbles.”</blockquote>
| |
|
| |
|
| | <br> |
|
| |
|
| Designing fileSHA with mailing list software gave us the space to explore the process of file sharing. Furthermore, we realized that this game has the potential to be played for an infinite amount of time. Software architectures like those of a mailing list allow for “necroposting,” We believe there is no shame in resurrecting conversations that are six months or ten years old, because at best it’s experienced as a collective sedimentation process that belongs as much to you as it does to those who wrote about it months to a decade earlier. Computers as rivers!
| | <small> |
| | | [[#Platframe Postscript|'''Karl Moubarak''''s bio.]] |
|
| |
|
| | '''André Fincato''' is a designer turned programmer. André joined the coop in 2017 after taking part in HDSA 2016 and then working on the H&D wiki re-organization by building a new website. His main areas of interest are: usership, p2p systems, software production, labor politics.</small> |
| | </div> |
| </div> | | </div> |