From 739ab60b0b7ead9cb0d7df73ca55f28536872de3 Mon Sep 17 00:00:00 2001 From: Davide Alberani Date: Thu, 8 Nov 2018 20:09:41 +0100 Subject: [PATCH] Mastodon bot --- Dockerfile | 14 ++ Dockerfile.mastodon | 27 +++ LICENSE | 201 +++++++++++++++++++ README.md | 38 ++++ cry-a-lot | 18 ++ maston-publish.py | 41 ++++ tap.grm | 464 ++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 803 insertions(+) create mode 100644 Dockerfile create mode 100644 Dockerfile.mastodon create mode 100644 LICENSE create mode 100644 README.md create mode 100755 cry-a-lot create mode 100755 maston-publish.py create mode 100644 tap.grm diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..7d84f54 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,14 @@ +FROM debian:stable-slim +LABEL \ + maintainer="Davide Alberani " + +RUN \ + apt-get update && \ + apt-get -y --no-install-recommends install \ + polygen && \ + rm -rf /var/lib/apt/lists/* + +COPY tap.grm cry-a-lot / +RUN chmod +x /cry-a-lot + +CMD [ "/cry-a-lot" ] diff --git a/Dockerfile.mastodon b/Dockerfile.mastodon new file mode 100644 index 0000000..97d2af1 --- /dev/null +++ b/Dockerfile.mastodon @@ -0,0 +1,27 @@ +FROM debian:stable-slim +LABEL \ + maintainer="Davide Alberani " + +RUN \ + apt-get update && \ + apt-get -y --no-install-recommends install \ + polygen \ + python3 \ + python3-cffi \ + python3-six \ + python3-tz \ + python3-decorator \ + python3-dateutil \ + python3-requests \ + python3-cryptography \ + python3-setuptools \ + python3-wheel \ + python3-pip && \ + pip3 install Mastodon.py && \ + rm -rf /var/lib/apt/lists/* + +COPY tap.grm cry-a-lot maston-publish.py / + +ENTRYPOINT ["python3", "/maston-publish.py"] + + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8dada3e --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md new file mode 100644 index 0000000..fd092c6 --- /dev/null +++ b/README.md @@ -0,0 +1,38 @@ +# Thoughts & Prayers + +Let's face it: we are all busy and lazy people. That, and our horrible attention span, conspire against us making us look like monsters in mourning times. + +But now we have Thoughts & Prayers! Thoughts & Prayers will save the world! + +Thoughts & Prayers is a [polygen](https://polygen.org/) grammar for busy people, helping them populating their Twitter (or even better, Mastodon!) timeline in time of need (i.e. "always"). + +This time it will totally work. + + +## Use + +* install **polygen** +* run **polygen tap.grm** +* feel a better person + + +## Mastodon bot + +A demo bot can be found at [@thoughts_and_prayers](https://botsin.space/@thoughts_and_prayers) + +You can use the content of the *Dockerfile.mastodon* file to create your own Mastodon bot; don't forget to run it specifying the **TAPBOT_TOKEN** environment variable. + + +# License + +Copyright 2018 Davide Alberani + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/cry-a-lot b/cry-a-lot new file mode 100755 index 0000000..cd2b094 --- /dev/null +++ b/cry-a-lot @@ -0,0 +1,18 @@ +#!/bin/bash +# +# this script should run inside a Docker container. +# +# If you want to use this grammar directly on your system, just run: +# polygen ./tap.grm + +PATH="${PATH}:/usr/games" + +TAP="$(polygen /tap.grm)" + +hashtag="$(echo "${TAP}" | cut -d '#' -f 2)" +if [ -n "${hashtag}" ] ; then + newhashtag="$(echo "${hashtag}" | sed "s@[ '\.-]*@@g" | tr '[[:upper:]]' '[[:lower:]]')" + TAP="$(echo "${TAP}" | sed "s@#${hashtag}@#${newhashtag}@")" +fi + +echo "${TAP}" diff --git a/maston-publish.py b/maston-publish.py new file mode 100755 index 0000000..a6f6237 --- /dev/null +++ b/maston-publish.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import os +import sys +import subprocess +from mastodon import Mastodon + +API_URL = 'https://botsin.space/' + +sys.stdout = open(sys.stdout.fileno(), mode='w', encoding='utf8', buffering=1) + +def getThoughtsAndPrayers(): + cmd = ['/cry-a-lot'] + process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + stdout, stderr = process.communicate() + try: + stdout = stdout.strip() + stdout = stdout.decode('utf8') + except: + return 'uh-oh: something was wrong with the encoding of the prayer; try again' + if process.returncode != 0: + return 'something terrible is happening: exit code: %s, stderr: %s' % ( + process.returncode, stderr.decode('utf8')) + if not stdout: + return 'sadness: the Thoughts & Prayers bottle was empty; try again' + return stdout + + +def serve(token): + tap = getThoughtsAndPrayers() + print('my thoughts & prayers: %s' % tap) + mastodon = Mastodon(access_token=token, api_base_url=API_URL) + mastodon.status_post(tap) + + +if __name__ == '__main__': + if 'TAPBOT_TOKEN' not in os.environ: + print("Please specify the Mastodon token in the TAPBOT_TOKEN environment variable") + sys.exit(1) + serve(token=os.environ['TAPBOT_TOKEN']) diff --git a/tap.grm b/tap.grm new file mode 100644 index 0000000..b9f6541 --- /dev/null +++ b/tap.grm @@ -0,0 +1,464 @@ +I ::= "title: Thoughts & Prayers\n" + ^ "author: Davide Alberani \n" + ^ "language: English\n" + ^ "status: beta\n" + ^ "topic: religion,society,shootings,disasters,doing-nothing,this-time-it-will-work\n" + ^ "audience: the ones who care\n" + ^ "created: 2018-11-08\n" +; + +S ::= BULLSHIT ; + +BULLSHIT ::= ( + TAP (to|for) [VICTIMS] TARGET | + our TAP are with [VICTIMS] TARGET | + "Je suis" TARGET | + "We are all" [with VICTIMS] TARGET | + ["We"] pray for [VICTIMS] TARGET) ^ ("."|"!") ["💔"|"❤"|"♡"|"🙏"] + ["#" ^ TARGET ^ EVENT]; + +TAP ::= thoughts (and|"&") prayers; + +VICTIMS ::= the [families of the] victims (in|of); + +EVENT := ( + +++shooting | + ++massacre | + flood | + fire | + earthquake | + disaster | + ++attack +) ; + +TARGET := ( + "Abidjan" | + "Abu Dhabi" | + "Abuja" | + "Accra" | + "Adamstown" | + "Addis Ababa" | + "Ahmedabad" | + "Ahvaz" | + "Alexandria" | + "Algiers" | + "Allahabad" | + "Almaty" | + "Alofi" | + "Amman" | + "Amsterdam" | + "Andorra la Vella" | + "Ankara" | + "Antananarivo" | + "Apia" | + "Ashgabat" | + "Asmara" | + "Astana" | + "Asunción" | + "Athens" | + "Auckland" | + "Avarua" | + "Baghdad" | + "Baku" | + "Bamako" | + "Bandar Seri Begawan" | + "Bandung" | + "Bangalore" | + "Bangkok" | + "Bangui" | + "Banjul" | + "Baoding" | + "Barcelona" | + "Barranquilla" | + "Basra" | + "Basseterre" | + "Beijing" | + "Beirut" | + "Belgrade" | + "Belmopan" | + "Belo Horizonte" | + "Berlin" | + "Bern" | + "Bhopal" | + "Birmingham" | + "Bishkek" | + "Bissau" | + "Bloemfontein" | + "Bogotá" | + "Brades Estate" | + "Brasília" | + "Bratislava" | + "Brazzaville" | + "Bridgetown" | + "Brisbane" | + "Brussels" | + "Bucharest" | + "Budapest" | + "Buenos Aires" | + "Bujumbura" | + "Bulawayo" | + "Busan" | + "Cairo" | + "Calgary" | + "Cali" | + "Caloocan" | + "Campinas" | + "Canberra" | + "Cape Town" | + "Caracas" | + "Cartagena" | + "Casablanca" | + "Castries" | + "Cetinje" | + "Changchun" | + "Changsha" | + "Chaozhou" | + "Charlotte Amalie" | + "Chengdu" | + "Chennai" | + "Chicago" | + "Chișinău" | + "Chittagong" | + "Chongqing" | + "Cockburn Town" | + "Cologne" | + "Colombo" | + "Conakry" | + "Copenhagen" | + "Córdoba" | + "Cotonou" | + "Curitiba" | + "Daegu" | + "Daejeon" | + "Dakar" | + "Dalian" | + "Dallas" | + "Damascus" | + "Dar es Salaam" | + "Davao City" | + "Delhi" | + "Dhaka" | + "Dili" | + "Djibouti" | + "Dodoma" | + "Doha" | + "Dongguan" | + "Douala" | + "Douglas" | + "Dubai" | + "Dublin" | + "Durban" | + "Dushanbe" | + "Edinburgh of the Seven Seas" | + "Ekurhuleni" | + "El Aioun" | + "Episkopi Cantonment" | + "Faisalabad" | + "Fez" | + "Flying Fish Cove" | + "Fortaleza" | + "Foshan" | + "Freetown" | + "Fukuoka" | + "Funafuti" | + "Fuzhou" | + "Gaborone" | + "Georgetown" | + "George Town" | + "Gibraltar" | + "Giza" | + "Guadalajara" | + "Guangzhou" | + "Guatemala City" | + "Guayaquil" | + "Gujranwala" | + "Gustavia" | + "Gwangju" | + "Hagåtña" | + "Hamburg" | + "Hamilton" | + "Hanga Roa" | + "Hangzhou" | + "Hanoi" | + "Harare" | + "Harbin" | + "Hargeisa" | + "Havana" | + "Hefei" | + "Helsinki" | + "Hiroshima" | + "Ho Chi Minh City" | + "Hong Kong" | + "Honiara" | + "Houston" | + "Hyderabad" | + "Ibadan" | + "Incheon" | + "Isfahan" | + "Islamabad" | + "Istanbul" | + "İzmir" | + "Jaipur" | + "Jakarta" | + "Jamestown" | + "Jarabulus" | + "Jeddah" | + "Jerusalem" | + "Jinan" | + "Johannesburg" | + "Juba" | + "Kabul" | + "Kampala" | + "Kano" | + "Kanpur" | + "Kaohsiung" | + "Karachi" | + "Karaj" | + "Kathmandu" | + "Kawasaki" | + "Kharkiv" | + "Khartoum" | + "Kiev" | + "Kigali" | + "King Edward Point" | + "Kingston" | + "Kingstown" | + "Kinshasa" | + "Kobe" | + "Kolkata" | + "Kuala Lumpur" | + "Kutaisi" | + "Kuwait City" | + "Kyoto" | + "Lagos" | + "Lahore" | + "Lanzhou" | + "La Paz" | + "Libreville" | + "Lilongwe" | + "Lima" | + "Lisbon" | + "Ljubljana" | + "Lobamba" | + "Lomé" | + "London" | + "Los Angeles" | + "Luanda" | + "Lucknow" | + "Lusaka" | + "Luxembourg" | + "Madrid" | + "Majuro" | + "Makassar" | + "Malabo" | + "Malé" | + "Managua" | + "Manama" | + "Mandalay" | + "Manila" | + "Maputo" | + "Maracaibo" | + "Marigot" | + "Maseru" | + "Mashhad" | + "Mata-Utu" | + "Mbabane" | + "Medan" | + "Medellin" | + "Melbourne" | + "Mexico City" | + "Milan" | + "Minsk" | + "Mogadishu" | + "Monaco" | + "Monrovia" | + "Monterrey" | + "Montevideo" | + "Montreal" | + "Moroni" | + "Moscow" | + "Mumbai" | + "Munich" | + "Muscat" | + "Nagoya" | + "Nagpur" | + "Nairobi" | + "Nanjing" | + "Nassau" | + "Naypyidaw" | + "N'Djamena" | + "New Delhi" | + "New Taipei City" | + "New York City" | + "Ngerulmud" | + "Niamey" | + "Nicosia" | + "Ningbo" | + "Nizhny Novgorod" | + "Nouakchott" | + "Nouméa" | + "Novosibirsk" | + "Nukuʻalofa" | + "Nuuk" | + "Omsk" | + "Oran" | + "Oranjestad" | + "Osaka" | + "Oslo" | + "Ottawa" | + "Ouagadougou" | + "Pago Pago" | + "Palembang" | + "Palestine" | + "Palikir" | + "Panama City" | + "Papeete" | + "Paramaribo" | + "Paris" | + "Patna" | + "Peshawar" | + "Philadelphia" | + "Philipsburg" | + "Phnom Penh" | + "Phoenix" | + "Plymouth" | + "Podgorica" | + "Port-au-Prince" | + "Port Louis" | + "Port Moresby" | + "Porto Alegre" | + "Port of Spain" | + "Porto-Novo" | + "Port Vila" | + "Prague" | + "Praia" | + "Pretoria" | + "Pristina" | + "Pune" | + "Putrajaya" | + "Pyongyang" | + "Qingdao" | + "Qom" | + "Quanzhou" | + "Quezon City" | + "Quito" | + "Rabat" | + "Rawalpindi" | + "Recife" | + "Reykjavík" | + "Riga" | + "Rio de Janeiro" | + "Riyadh" | + "Road Town" | + "Rome" | + "Rosario" | + "Roseau" | + "Rostov-on-Don" | + "Saint Petersburg" | + "Saipan" | + "Saitama" | + "Salvador" | + "Sana'a" | + "San Antonio" | + "San Diego" | + "San José" | + "San Juan" | + "San Marino" | + "San Salvador" | + "Santa Cruz de la Sierra" | + "Santiago" | + "Santo Domingo" | + "São Paulo" | + "São Tomé" | + "Sapporo" | + "Sarajevo" | + "Semarang" | + "Seoul" | + "Shanghai" | + "Shantou" | + "Shenyang" | + "Shenzhen" | + "Shijiazhuang" | + "Shiraz" | + "Singapore" | + "Skopje" | + "Sofia" | + "Sri Jayawardenepura Kotte" | + "Stanley" | + "Stepanakert" | + "St. George's" | + "St. Helier" | + "St. John's" | + "Stockholm" | + "St. Peter Port" | + "St. Pierre" | + "Sucre" | + "Sukhumi" | + "Surabaya" | + "Surat" | + "Suva" | + "Suwon" | + "Suzhou" | + "Sydney" | + "Tabriz" | + "Taichung" | + "Tainan" | + "Taipei" | + "Tallinn" | + "Tangshan" | + "Tarawa" | + "Tashkent" | + "Tbilisi" | + "T'bilisi" | + "Tegucigalpa" | + "Tehran" | + "The Valley" | + "Thimphu" | + "Tianjin" | + "Tifariti" | + "Tijuana" | + "Tirana" | + "Tiraspol" | + "Tokyo" | + "Toronto" | + "Tórshavn" | + "Tripoli" | + "Tskhinvali" | + "Tunis" | + "Ulaanbaatar" | + "Ulsan" | + "Vaduz" | + "Valletta" | + "Vatican City" | + "Victoria" | + "Vienna" | + "Vientiane" | + "Vijayawada" | + "Vilnius" | + "Visakhapatnam" | + "Warsaw" | + "Washington" | + "Wellington" | + "Wenzhou" | + "West Island" | + "Willemstad" | + "Windhoek" | + "Wuhan" | + "Xiamen" | + "Xi'an" | + "Yamoussoukro" | + "Yangon" | + "Yaoundé" | + "Yaren" | + "Yekaterinburg" | + "Yerevan" | + "Yokohama" | + "Zagreb" | + "Zhengzhou" | + "Zhongshan" | + "Zunyi" | + "Bologna" | + "Casalpusterlengo" | + "Vergate sul Membro" | + "D come Domodossola" +) ;