From f78773bb87721442a1243292cacbb10a4e8124fb Mon Sep 17 00:00:00 2001 From: hacklab Date: Tue, 29 Sep 2026 10:10:54 +0200 Subject: [PATCH] Web de la acampada del 26S MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Home con directo, comunicados y organización. HTML y CSS, sin JS. Configuración de nginx, timer del directo y limpieza de EXIF. --- LICENSE | 661 ++++++++++++++++++ README.md | 90 +++ deploy/directo.service | 16 + deploy/directo.timer | 9 + deploy/hub.conf | 16 + deploy/nginx.conf | 54 ++ site/comunicados/2026-09-26-convocatoria.html | 31 + site/comunicados/2026-09-27-primer-dia.html | 31 + site/css/main.css | 98 +++ site/fonts/OFL.txt | 93 +++ site/fonts/anton.woff2 | Bin 0 -> 15800 bytes site/index.html | 71 ++ tools/directo.py | 89 +++ tools/limpia-img.sh | 26 + tools/ultimos.js | 50 ++ 15 files changed, 1335 insertions(+) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 deploy/directo.service create mode 100644 deploy/directo.timer create mode 100644 deploy/hub.conf create mode 100644 deploy/nginx.conf create mode 100644 site/comunicados/2026-09-26-convocatoria.html create mode 100644 site/comunicados/2026-09-27-primer-dia.html create mode 100644 site/css/main.css create mode 100644 site/fonts/OFL.txt create mode 100644 site/fonts/anton.woff2 create mode 100644 site/index.html create mode 100755 tools/directo.py create mode 100755 tools/limpia-img.sh create mode 100755 tools/ultimos.js diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..be3f7b2 --- /dev/null +++ b/LICENSE @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/README.md b/README.md new file mode 100644 index 0000000..80f62b1 --- /dev/null +++ b/README.md @@ -0,0 +1,90 @@ +# acampada26s.net + +Web de la acampada del 26S en Madrid. Comunicados, directo y cómo organizarse. + +HTML y CSS. Sin JavaScript en el navegador, sin cookies, sin analítica y sin +peticiones a terceros. La tipografía va dentro del repo. + +La comunicación viva no depende de esta web: va por un pub de +[OASIS](https://code.03c8.net/krakenslab/oasis) (Secure Scuttlebutt). Si la web +cae o la tiran, el pub y lo publicado siguen en la red. + +## Estructura + +``` +site/ lo que se sirve (copiar tal cual a /var/www/acampada26s.net) +deploy/ nginx y timer de systemd +tools/ limpiar imágenes y regenerar el directo +``` + +## Publicar un comunicado + +1. Copiar `site/comunicados/2026-09-26-convocatoria.html` a + `site/comunicados/AAAA-MM-DD-titulo.html` y cambiar título, fecha y texto. +2. Añadir un `
  • ` arriba del todo en la lista `#comunicados` de `site/index.html`. +3. Fotos a `site/img/`, siempre limpias antes: + + ``` + tools/limpia-img.sh site/img/*.jpg + ``` + + El EXIF lleva GPS, modelo de móvil y hora. Además: caras tapadas salvo + permiso expreso. + +4. Toda imagen con `alt`, `width` y `height`. + +## Despliegue + +Requisitos: nginx, certbot. Para el directo: el pub OASIS en la misma máquina, +Node 22 y Python 3.9+. + +``` +rsync -a --delete site/ /var/www/acampada26s.net/ +cp deploy/nginx.conf /etc/nginx/sites-available/acampada26s.net +cp deploy/hub.conf /etc/nginx/snippets/acampada26s-hub.conf +ln -s ../sites-available/acampada26s.net /etc/nginx/sites-enabled/ +nginx -t && systemctl reload nginx +``` + +`rsync --delete` borra el bloque directo generado; el timer lo repone en un minuto. + +### Pub OASIS + +El pub se arranca con `sh oasis.sh server` y el HUB web escucha en `:3000`. +Conviene que escuche solo en local (`--host=127.0.0.1`): nginx publica `/c` +en solo lectura (GET/HEAD) y le quita la IP del visitante. + +Invite para la home: `sh oasis.sh invite 1000`, y pegarlo en `#organizate`. + +### Directo + +`tools/ultimos.js` lee los últimos posts de la identidad de la acampada por el +socket local del sbot. `tools/directo.py` los escribe en `index.html` entre +`` y ``, escapado y con escritura +atómica. Sigue siendo un fichero estático: aguanta mucha carga y no hace falta +JavaScript. + +``` +cp -r . /opt/26s +cp deploy/directo.service deploy/directo.timer /etc/systemd/system/ +# editar FEED, OASIS_DIR y User en directo.service +systemctl enable --now directo.timer +``` + +A mano: + +``` +OASIS_DIR=~/oasis node tools/ultimos.js @feed.ed25519 5 | python3 tools/directo.py site/index.html +``` + +## Comprobaciones antes de subir + +``` +grep -rniE ' HUB clearnet de OASIS (solo lectura) del pub de la acampada. + +server_tokens off; + +# Logs sin IP completa: se guarda solo la /24. +map $remote_addr $ip_anon { + ~(?P\d+\.\d+\.\d+)\.\d+ $ip.0; + ~(?P[^:]+:[^:]+): $ip::; + default 0.0.0.0; +} +log_format anon '$ip_anon [$time_local] "$request" $status $body_bytes_sent'; + +server { + listen 80; + listen [::]:80; + server_name acampada26s.net www.acampada26s.net; + return 301 https://acampada26s.net$request_uri; +} + +server { + listen 443 ssl http2; + listen [::]:443 ssl http2; + server_name acampada26s.net www.acampada26s.net; + + ssl_certificate /etc/letsencrypt/live/acampada26s.net/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/acampada26s.net/privkey.pem; + + access_log /var/log/nginx/acampada26s.access.log anon; + + root /var/www/acampada26s.net; + index index.html; + + add_header Content-Security-Policy "default-src 'none'; style-src 'self'; img-src 'self'; font-src 'self'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'" always; + add_header Strict-Transport-Security "max-age=63072000" always; + add_header X-Content-Type-Options "nosniff" always; + add_header Referrer-Policy "no-referrer" always; + add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), interest-cohort=()" always; + + location / { + limit_except GET HEAD { deny all; } + try_files $uri $uri/ =404; + } + + location ~* \.(css|woff2|jpg|jpeg|png|webp)$ { + limit_except GET HEAD { deny all; } + expires 7d; + } + + # HUB de OASIS. Trae CSS inline, así que hub.conf redefine las cabeceras sin la CSP. + location = /c { include /etc/nginx/snippets/acampada26s-hub.conf; } + location ^~ /c/ { include /etc/nginx/snippets/acampada26s-hub.conf; } +} diff --git a/site/comunicados/2026-09-26-convocatoria.html b/site/comunicados/2026-09-26-convocatoria.html new file mode 100644 index 0000000..9263acf --- /dev/null +++ b/site/comunicados/2026-09-26-convocatoria.html @@ -0,0 +1,31 @@ + + + + + + + +Convocatoria 26S · Acampada 26S + + + + + +
    +

    Acampada 26S

    +
    + +
    +
    +

    Convocatoria 26S

    +

    Borrador

    +

    Texto de la convocatoria pendiente de aprobar en asamblea.

    +

    Lugar, hora y motivos van aquí.

    +
    +
    + +
    + Textos CC BY-SA 4.0 · Código AGPL-3.0 · Fuente +
    + + diff --git a/site/comunicados/2026-09-27-primer-dia.html b/site/comunicados/2026-09-27-primer-dia.html new file mode 100644 index 0000000..f54b081 --- /dev/null +++ b/site/comunicados/2026-09-27-primer-dia.html @@ -0,0 +1,31 @@ + + + + + + + +Primer día en la plaza · Acampada 26S + + + + + +
    +

    Acampada 26S

    +
    + +
    +
    +

    Primer día en la plaza

    +

    Borrador

    +

    Crónica de la primera jornada pendiente de aprobar en asamblea.

    +

    Las fotos se suben limpias de metadatos: tools/limpia-img.sh.

    +
    +
    + +
    + Textos CC BY-SA 4.0 · Código AGPL-3.0 · Fuente +
    + + diff --git a/site/css/main.css b/site/css/main.css new file mode 100644 index 0000000..9c7da65 --- /dev/null +++ b/site/css/main.css @@ -0,0 +1,98 @@ +@font-face { + font-family: "Anton"; + src: url("../fonts/anton.woff2") format("woff2"); + font-display: swap; +} + +:root { + --bg: #fff; + --fg: #000; + --acc: #ff1493; + --bd: 3px solid var(--fg); + --gap: 12px; + --tit: Impact, "Anton", "Arial Narrow", sans-serif; + --txt: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; +} + +*, *::before, *::after { box-sizing: border-box; } + +html { color-scheme: light; } + +body { + margin: 0; + background: var(--bg); + color: var(--fg); + font: 17px/1.5 var(--txt); +} + +img { max-width: 100%; height: auto; display: block; } + +a { color: inherit; } + +.w { max-width: 1100px; margin: 0 auto; padding: 0 16px; } + +h1, h2, h3, .cuadro, .bt { + font-family: var(--tit); + font-weight: 400; + text-transform: uppercase; + letter-spacing: .01em; + line-height: 1.05; +} + +h1 { font-size: clamp(48px, 11vw, 120px); margin: 24px 0 16px; } +h2 { font-size: 40px; margin: 48px 0 16px; border-bottom: var(--bd); padding-bottom: 6px; } +h3 { font-size: 26px; margin: 0 0 6px; } + +/* cuadros y botones */ +.cuadros, .botonera { display: grid; gap: var(--gap); padding: 0; margin: 0; list-style: none; } +.cuadros { grid-template-columns: repeat(3, 1fr); } +.botonera { grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); margin-top: var(--gap); } + +.cuadro, .bt { + display: block; + border: var(--bd); + background: var(--bg); + text-decoration: none; + text-align: center; + transition: transform .12s, box-shadow .12s, background-color .12s; +} +.cuadro { font-size: 30px; padding: 28px 12px; } +.bt { font-size: 20px; padding: 12px; } +.volver { display: inline-block; margin-top: 24px; } + +.cuadro:hover, .cuadro:focus-visible, +.bt:hover, .bt:focus-visible { + background: var(--acc); + transform: translateY(-4px); + box-shadow: 0 4px 0 var(--fg); + outline: none; +} + +/* comunicados */ +.lista { list-style: none; margin: 0; padding: 0; } +.lista > li { border-bottom: 1px solid var(--fg); padding: 20px 0; } +.lista a:hover, .lista a:focus-visible { color: var(--acc); } +time { font-family: var(--tit); font-size: 18px; } +.borrador { border: var(--bd); padding: 0 6px; font-family: var(--tit); font-size: 14px; } + +article { max-width: 720px; } +article p { margin: 0 0 1em; } + +code, pre { + font: 14px/1.4 ui-monospace, "DejaVu Sans Mono", monospace; + word-break: break-all; +} +pre { border: var(--bd); padding: 12px; white-space: pre-wrap; margin: 0 0 1em; } + +footer { margin: 64px 0 24px; border-top: var(--bd); padding-top: 12px; font-size: 14px; } + +@media (max-width: 640px) { + .cuadros { grid-template-columns: 1fr; } + h2 { font-size: 32px; } +} + +@media (prefers-reduced-motion: reduce) { + .cuadro, .bt { transition: none; } + .cuadro:hover, .cuadro:focus-visible, + .bt:hover, .bt:focus-visible { transform: none; } +} diff --git a/site/fonts/OFL.txt b/site/fonts/OFL.txt new file mode 100644 index 0000000..93fedde --- /dev/null +++ b/site/fonts/OFL.txt @@ -0,0 +1,93 @@ +Copyright 2020 The Anton Project Authors (https://github.com/googlefonts/AntonFont.git) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/site/fonts/anton.woff2 b/site/fonts/anton.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..46fd713ec5d27a15a18e24aeafd9d2ec29a1ab7d GIT binary patch literal 15800 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 + + + + + + +Acampada 26S + + + + + +
    +

    Acampada 26S

    + + +
    + +
    + + + +
    +

    Comunicados

    +
      +
    1. + Borrador +

      Primer día en la plaza

      +

      Resumen de la primera jornada y de las asambleas convocadas.

      +
    2. +
    3. + Borrador +

      Convocatoria 26S

      +

      Por qué acampamos, dónde y cómo sumarse.

      +
    4. +
    +
    + +
    +

    Organízate

    +

    La acampada publica en su propio pub de OASIS, una red social libre sobre Secure Scuttlebutt. Sin servidores de empresa y sin cuentas que puedan cerrar desde fuera. Lo que se publica en la plaza aparece en Directo.

    +

    Entrar al pub

    +
      +
    1. Instala OASIS en el ordenador o la APK en el móvil.
    2. +
    3. Abre OASIS, ve a Invites y pega este código:
    4. +
    +
    acampada26s.net:8008:@CAMBIAR.ed25519~CAMBIAR
    +

    A partir de ahí puedes leer, publicar y hablar con el resto de la acampada aunque esta web se caiga.

    +
    +
    + +
    + Textos CC BY-SA 4.0 · Código AGPL-3.0 · Fuente +
    + + diff --git a/tools/directo.py b/tools/directo.py new file mode 100755 index 0000000..c0949c8 --- /dev/null +++ b/tools/directo.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python3 +"""Reescribe el bloque DIRECTO de index.html con los últimos posts del pub. + +Lee de stdin el JSON de tools/ultimos.js y sustituye lo que haya entre + y . Escritura atómica: el +servidor web nunca ve un fichero a medias. + + node tools/ultimos.js @feed.ed25519 5 | python3 tools/directo.py /var/www/acampada26s.net/index.html +""" +import html +import json +import os +import re +import sys +import tempfile +from datetime import datetime +from urllib.parse import quote +from zoneinfo import ZoneInfo + +INI = "" +FIN = "" +MAX = 400 # caracteres por post +TZ = ZoneInfo("Europe/Madrid") + + +def limpia(texto): + # fuera markdown de imágenes/enlaces y referencias ssb, queda el texto + texto = re.sub(r"!\[[^\]]*\]\([^)]*\)", "", texto) + texto = re.sub(r"\[([^\]]*)\]\([^)]*\)", r"\1", texto) + texto = " ".join(texto.split()) + if len(texto) > MAX: + texto = texto[:MAX].rsplit(" ", 1)[0] + "…" + return texto + + +def bloque(posts): + li = [] + for p in posts: + t = datetime.fromtimestamp(p["ts"] / 1000, tz=TZ) + img = "" + if p.get("img"): + src = "/c/blob/" + quote(p["img"], safe="") + img = f'\n ' + li.append( + "
  • \n" + f' {img}\n' + f"

    {html.escape(limpia(p['text']))}

    \n" + "
  • " + ) + if not li: + return f"{INI}\n {FIN}" + return ( + f'{INI}\n
    \n

    Directo

    \n' + f'
      \n{chr(10).join(li)}\n
    \n' + f'

    Todo en OASIS

    \n
    \n {FIN}' + ) + + +def main(): + if len(sys.argv) != 2: + sys.exit("uso: ... | directo.py ruta/index.html") + ruta = sys.argv[1] + posts = json.load(sys.stdin) + if not isinstance(posts, list): + sys.exit("entrada no es una lista") + + with open(ruta, encoding="utf-8") as f: + doc = f.read() + i, j = doc.find(INI), doc.find(FIN) + if i < 0 or j < i: + sys.exit("no están las marcas directo:inicio / directo:fin") + nuevo = doc[:i] + bloque(posts) + doc[j + len(FIN):] + if nuevo == doc: + return + + d = os.path.dirname(os.path.abspath(ruta)) + fd, tmp = tempfile.mkstemp(dir=d, prefix=".index.") + try: + with os.fdopen(fd, "w", encoding="utf-8") as f: + f.write(nuevo) + os.chmod(tmp, 0o644) + os.replace(tmp, ruta) + except BaseException: + os.unlink(tmp) + raise + + +if __name__ == "__main__": + main() diff --git a/tools/limpia-img.sh b/tools/limpia-img.sh new file mode 100755 index 0000000..ef902dc --- /dev/null +++ b/tools/limpia-img.sh @@ -0,0 +1,26 @@ +#!/bin/sh +# Quita metadatos (EXIF, GPS, modelo de móvil) de las imágenes antes de subirlas. +# Uso: tools/limpia-img.sh foto1.jpg foto2.png ... +# Necesita exiftool (libimage-exiftool-perl) o mat2. +set -eu + +[ $# -gt 0 ] || { echo "uso: $0 imagen..." >&2; exit 1; } + +if command -v exiftool >/dev/null 2>&1; then + exiftool -all= -overwrite_original -- "$@" +elif command -v mat2 >/dev/null 2>&1; then + for f in "$@"; do + mat2 --inplace -- "$f" + done +else + echo "falta exiftool o mat2" >&2 + exit 1 +fi + +# comprobación: no debe quedar GPS +if command -v exiftool >/dev/null 2>&1; then + if exiftool -q -q -if '$GPSLatitude' -p '$FileName' -- "$@" 2>/dev/null | grep .; then + echo "ojo: quedan coordenadas GPS en las de arriba" >&2 + exit 1 + fi +fi diff --git a/tools/ultimos.js b/tools/ultimos.js new file mode 100755 index 0000000..dc43757 --- /dev/null +++ b/tools/ultimos.js @@ -0,0 +1,50 @@ +#!/usr/bin/env node +// Saca los últimos posts de un feed SSB en JSON, para tools/directo.py. +// Se ejecuta en el servidor del pub, con el sbot de OASIS arrancado. +// Uso: OASIS_DIR=~/oasis node tools/ultimos.js @feed.ed25519 [N] +const path = require('path'); + +const dir = process.env.OASIS_DIR || path.join(process.env.HOME, 'oasis'); +const ssbConfig = require(path.join(dir, 'src', 'server', 'ssb_config')); +const ssbClient = require(path.join(dir, 'src', 'server', 'node_modules', 'ssb-client')); + +const id = process.argv[2]; +const n = Math.min(50, Math.max(1, parseInt(process.argv[3] || '5', 10))); +if (!id || !id.startsWith('@')) { + console.error('uso: node tools/ultimos.js @feed.ed25519 [N]'); + process.exit(1); +} + +const pub = (ssbConfig.keys.public || '').replace('.ed25519', ''); +const remote = `unix:${path.join(ssbConfig.path, 'socket')}~noauth:${pub}`; + +ssbClient(ssbConfig.keys, { remote, caps: ssbConfig.caps }).then((ssb) => { + const out = []; + const src = ssb.createUserStream({ id, reverse: true, limit: 200 }); + const next = () => src(null, (end, msg) => { + if (end || out.length >= n) { + src(true, () => {}); + ssb.close(() => console.log(JSON.stringify(out))); + return; + } + const c = msg.value && msg.value.content; + if (c && c.type === 'post' && typeof c.text === 'string') { + const img = (Array.isArray(c.mentions) ? c.mentions : []) + .find((m) => m && typeof m.link === 'string' && m.link.startsWith('&') && + typeof m.type === 'string' && m.type.startsWith('image/')); + // OASIS no siempre pone type en mentions: se mira también el markdown + const md = c.text.match(/!\[[^\]]*\]\((&[A-Za-z0-9+/=]+\.sha256)\)/); + out.push({ + key: msg.key, + ts: msg.value.timestamp, + text: c.text, + img: img ? img.link : (md ? md[1] : null), + }); + } + next(); + }); + next(); +}).catch((e) => { + console.error(e.message); + process.exit(1); +});