Browse Source

First commit.
History is present

cocco_git 6 years ago
commit
cabebe4395

+ 1 - 0
README.md

@@ -0,0 +1 @@
+

+ 16 - 0
dbs/pinopisolo.db

@@ -0,0 +1,16 @@
+{"actions": ["search_and_retweet"], "buddy": ["InfoAntifa", "LibreriAntigone", "romaoccupata", "Assospartaco", "BANDA_BASSOTTI", "rivamesta", "zeropregi", "progettoDegage", "contropiano", "DinamoPress", "ilmanifesto", "Radiondarossa", "repubblica", "notav_info", "Infoaut", "sap_clandestina", "zerocalcare", "FPrenestino", "AnpiRoma", "RFeminista_", "RomaAntifa", "AntifaOstia", "romattiva", "MilitantBlog", "RATM", "matteosalvinimi\u00a0", "gruppohobbit\u00a0", "CircoloFuturista", "MSR_cat\u00a0", "Occidentale", "OrdineNuovo", "romatoday\u00a0", "PBT_Torino", "Nigel_Farage", "UKIP", "SimoneCasaPound\u00a0", "MarcelloRuffo", "IannoneCpi", "ilgiornale\u00a0", "ChiaraScalzi85\u00a0", "BloccoStudentesco\u00a0", "prog_sociale", "ForzaNuova\u00a0", "AlbaDoratait\u00a0", "distefanoTW\u00a0", "CasaPoundItalia\u00a0", "giorgiameloni", "FratellidItalia"], "hash": ["fascismo", "antifascismo", "razzismo", "italia", "italiano", "italiaglitaliani", "stopinvasione", "puliziaetnica", "mussolini", "quandoceralui", "hitler", "farequadrato", "apologia", "nazismo", "antinazismo", "fakenews", "complotto", "noeuro", "scontri", "centrisociali", "occupazione", "lavoro", "sinistra", "manifestazione", "blackbloc", "vandalismo", "fanatismo", "destra", "parlamento", "violenza", "polizia", "esercito", "rom", "campirom", "roma", "guerra", "sciopero", "precari", "casa", "mafia", "camorra", "ndrangheta", "sindacato", "clandestino", "immigrato", "immigrati", "barconi", "negri", "cassazione", "pd", "leganord", "fdi", "an", "grillo", "m5s", "donne", "violenzasulledonne", "bambini", "famiglia", "dio", "patria", "difesa", "nazione", "paese", "madeinitaly", "salvini", "populismo", "casapound", "lepen", "schifo", "feccia", "odio", "amore", "forzanuova", "forteprenestino", "nietsche", "ezrapound", "democrazia", "politica", "votare", "elezioni", "parlamento"], "time": 1509234065}
+{"actions": ["search_and_retweet"], "buddy": ["InfoAntifa", "LibreriAntigone", "romaoccupata", "Assospartaco", "BANDA_BASSOTTI", "rivamesta", "zeropregi", "progettoDegage", "contropiano", "DinamoPress", "ilmanifesto", "Radiondarossa", "repubblica", "notav_info", "Infoaut", "sap_clandestina", "zerocalcare", "FPrenestino", "AnpiRoma", "RFeminista_", "RomaAntifa", "AntifaOstia", "romattiva", "MilitantBlog", "RATM", "matteosalvinimi\u00a0", "gruppohobbit\u00a0", "CircoloFuturista", "MSR_cat\u00a0", "Occidentale", "OrdineNuovo", "romatoday\u00a0", "PBT_Torino", "Nigel_Farage", "UKIP", "SimoneCasaPound\u00a0", "MarcelloRuffo", "IannoneCpi", "ilgiornale\u00a0", "ChiaraScalzi85\u00a0", "BloccoStudentesco\u00a0", "prog_sociale", "ForzaNuova\u00a0", "AlbaDoratait\u00a0", "distefanoTW\u00a0", "CasaPoundItalia\u00a0", "giorgiameloni", "FratellidItalia"], "hash": ["fascismo", "antifascismo", "razzismo", "italia", "italiano", "italiaglitaliani", "stopinvasione", "puliziaetnica", "mussolini", "quandoceralui", "hitler", "farequadrato", "apologia", "nazismo", "antinazismo", "fakenews", "complotto", "noeuro", "scontri", "centrisociali", "occupazione", "lavoro", "sinistra", "manifestazione", "blackbloc", "vandalismo", "fanatismo", "destra", "parlamento", "violenza", "polizia", "esercito", "rom", "campirom", "roma", "guerra", "sciopero", "precari", "casa", "mafia", "camorra", "ndrangheta", "sindacato", "clandestino", "immigrato", "immigrati", "barconi", "negri", "cassazione", "pd", "leganord", "fdi", "an", "grillo", "m5s", "donne", "violenzasulledonne", "bambini", "famiglia", "dio", "patria", "difesa", "nazione", "paese", "madeinitaly", "salvini", "populismo", "casapound", "lepen", "schifo", "feccia", "odio", "amore", "forzanuova", "forteprenestino", "nietsche", "ezrapound", "democrazia", "politica", "votare", "elezioni", "parlamento"], "time": 1509234070}
+{"actions": ["search_and_retweet"], "buddy": ["InfoAntifa", "LibreriAntigone", "romaoccupata", "Assospartaco", "BANDA_BASSOTTI", "rivamesta", "zeropregi", "progettoDegage", "contropiano", "DinamoPress", "ilmanifesto", "Radiondarossa", "repubblica", "notav_info", "Infoaut", "sap_clandestina", "zerocalcare", "FPrenestino", "AnpiRoma", "RFeminista_", "RomaAntifa", "AntifaOstia", "romattiva", "MilitantBlog", "RATM", "matteosalvinimi\u00a0", "gruppohobbit\u00a0", "CircoloFuturista", "MSR_cat\u00a0", "Occidentale", "OrdineNuovo", "romatoday\u00a0", "PBT_Torino", "Nigel_Farage", "UKIP", "SimoneCasaPound\u00a0", "MarcelloRuffo", "IannoneCpi", "ilgiornale\u00a0", "ChiaraScalzi85\u00a0", "BloccoStudentesco\u00a0", "prog_sociale", "ForzaNuova\u00a0", "AlbaDoratait\u00a0", "distefanoTW\u00a0", "CasaPoundItalia\u00a0", "giorgiameloni", "FratellidItalia"], "hash": ["fascismo", "antifascismo", "razzismo", "italia", "italiano", "italiaglitaliani", "stopinvasione", "puliziaetnica", "mussolini", "quandoceralui", "hitler", "farequadrato", "apologia", "nazismo", "antinazismo", "fakenews", "complotto", "noeuro", "scontri", "centrisociali", "occupazione", "lavoro", "sinistra", "manifestazione", "blackbloc", "vandalismo", "fanatismo", "destra", "parlamento", "violenza", "polizia", "esercito", "rom", "campirom", "roma", "guerra", "sciopero", "precari", "casa", "mafia", "camorra", "ndrangheta", "sindacato", "clandestino", "immigrato", "immigrati", "barconi", "negri", "cassazione", "pd", "leganord", "fdi", "an", "grillo", "m5s", "donne", "violenzasulledonne", "bambini", "famiglia", "dio", "patria", "difesa", "nazione", "paese", "madeinitaly", "salvini", "populismo", "casapound", "lepen", "schifo", "feccia", "odio", "amore", "forzanuova", "forteprenestino", "nietsche", "ezrapound", "democrazia", "politica", "votare", "elezioni", "parlamento"], "time": 1509234632}
+{"actions": ["search_and_retweet"], "buddy": ["InfoAntifa", "LibreriAntigone", "romaoccupata", "Assospartaco", "BANDA_BASSOTTI", "rivamesta", "zeropregi", "progettoDegage", "contropiano", "DinamoPress", "ilmanifesto", "Radiondarossa", "repubblica", "notav_info", "Infoaut", "sap_clandestina", "zerocalcare", "FPrenestino", "AnpiRoma", "RFeminista_", "RomaAntifa", "AntifaOstia", "romattiva", "MilitantBlog", "RATM", "matteosalvinimi\u00a0", "gruppohobbit\u00a0", "CircoloFuturista", "MSR_cat\u00a0", "Occidentale", "OrdineNuovo", "romatoday\u00a0", "PBT_Torino", "Nigel_Farage", "UKIP", "SimoneCasaPound\u00a0", "MarcelloRuffo", "IannoneCpi", "ilgiornale\u00a0", "ChiaraScalzi85\u00a0", "BloccoStudentesco\u00a0", "prog_sociale", "ForzaNuova\u00a0", "AlbaDoratait\u00a0", "distefanoTW\u00a0", "CasaPoundItalia\u00a0", "giorgiameloni", "FratellidItalia"], "hash": ["fascismo", "antifascismo", "razzismo", "italia", "italiano", "italiaglitaliani", "stopinvasione", "puliziaetnica", "mussolini", "quandoceralui", "hitler", "farequadrato", "apologia", "nazismo", "antinazismo", "fakenews", "complotto", "noeuro", "scontri", "centrisociali", "occupazione", "lavoro", "sinistra", "manifestazione", "blackbloc", "vandalismo", "fanatismo", "destra", "parlamento", "violenza", "polizia", "esercito", "rom", "campirom", "roma", "guerra", "sciopero", "precari", "casa", "mafia", "camorra", "ndrangheta", "sindacato", "clandestino", "immigrato", "immigrati", "barconi", "negri", "cassazione", "pd", "leganord", "fdi", "an", "grillo", "m5s", "donne", "violenzasulledonne", "bambini", "famiglia", "dio", "patria", "difesa", "nazione", "paese", "madeinitaly", "salvini", "populismo", "casapound", "lepen", "schifo", "feccia", "odio", "amore", "forzanuova", "forteprenestino", "nietsche", "ezrapound", "democrazia", "politica", "votare", "elezioni", "parlamento"], "time": 1509234658}
+{"actions": ["search_and_retweet"], "buddy": ["InfoAntifa", "LibreriAntigone", "romaoccupata", "Assospartaco", "BANDA_BASSOTTI", "rivamesta", "zeropregi", "progettoDegage", "contropiano", "DinamoPress", "ilmanifesto", "Radiondarossa", "repubblica", "notav_info", "Infoaut", "sap_clandestina", "zerocalcare", "FPrenestino", "AnpiRoma", "RFeminista_", "RomaAntifa", "AntifaOstia", "romattiva", "MilitantBlog", "RATM", "matteosalvinimi\u00a0", "gruppohobbit\u00a0", "CircoloFuturista", "MSR_cat\u00a0", "Occidentale", "OrdineNuovo", "romatoday\u00a0", "PBT_Torino", "Nigel_Farage", "UKIP", "SimoneCasaPound\u00a0", "MarcelloRuffo", "IannoneCpi", "ilgiornale\u00a0", "ChiaraScalzi85\u00a0", "BloccoStudentesco\u00a0", "prog_sociale", "ForzaNuova\u00a0", "AlbaDoratait\u00a0", "distefanoTW\u00a0", "CasaPoundItalia\u00a0", "giorgiameloni", "FratellidItalia"], "hash": ["fascismo", "antifascismo", "razzismo", "italia", "italiano", "italiaglitaliani", "stopinvasione", "puliziaetnica", "mussolini", "quandoceralui", "hitler", "farequadrato", "apologia", "nazismo", "antinazismo", "fakenews", "complotto", "noeuro", "scontri", "centrisociali", "occupazione", "lavoro", "sinistra", "manifestazione", "blackbloc", "vandalismo", "fanatismo", "destra", "parlamento", "violenza", "polizia", "esercito", "rom", "campirom", "roma", "guerra", "sciopero", "precari", "casa", "mafia", "camorra", "ndrangheta", "sindacato", "clandestino", "immigrato", "immigrati", "barconi", "negri", "cassazione", "pd", "leganord", "fdi", "an", "grillo", "m5s", "donne", "violenzasulledonne", "bambini", "famiglia", "dio", "patria", "difesa", "nazione", "paese", "madeinitaly", "salvini", "populismo", "casapound", "lepen", "schifo", "feccia", "odio", "amore", "forzanuova", "forteprenestino", "nietsche", "ezrapound", "democrazia", "politica", "votare", "elezioni", "parlamento"], "time": 1509234672}
+{"actions": ["search_and_retweet"], "buddy": ["InfoAntifa", "LibreriAntigone", "romaoccupata", "Assospartaco", "BANDA_BASSOTTI", "rivamesta", "zeropregi", "progettoDegage", "contropiano", "DinamoPress", "ilmanifesto", "Radiondarossa", "repubblica", "notav_info", "Infoaut", "sap_clandestina", "zerocalcare", "FPrenestino", "AnpiRoma", "RFeminista_", "RomaAntifa", "AntifaOstia", "romattiva", "MilitantBlog", "RATM", "matteosalvinimi\u00a0", "gruppohobbit\u00a0", "CircoloFuturista", "MSR_cat\u00a0", "Occidentale", "OrdineNuovo", "romatoday\u00a0", "PBT_Torino", "Nigel_Farage", "UKIP", "SimoneCasaPound\u00a0", "MarcelloRuffo", "IannoneCpi", "ilgiornale\u00a0", "ChiaraScalzi85\u00a0", "BloccoStudentesco\u00a0", "prog_sociale", "ForzaNuova\u00a0", "AlbaDoratait\u00a0", "distefanoTW\u00a0", "CasaPoundItalia\u00a0", "giorgiameloni", "FratellidItalia"], "hash": ["fascismo", "antifascismo", "razzismo", "italia", "italiano", "italiaglitaliani", "stopinvasione", "puliziaetnica", "mussolini", "quandoceralui", "hitler", "farequadrato", "apologia", "nazismo", "antinazismo", "fakenews", "complotto", "noeuro", "scontri", "centrisociali", "occupazione", "lavoro", "sinistra", "manifestazione", "blackbloc", "vandalismo", "fanatismo", "destra", "parlamento", "violenza", "polizia", "esercito", "rom", "campirom", "roma", "guerra", "sciopero", "precari", "casa", "mafia", "camorra", "ndrangheta", "sindacato", "clandestino", "immigrato", "immigrati", "barconi", "negri", "cassazione", "pd", "leganord", "fdi", "an", "grillo", "m5s", "donne", "violenzasulledonne", "bambini", "famiglia", "dio", "patria", "difesa", "nazione", "paese", "madeinitaly", "salvini", "populismo", "casapound", "lepen", "schifo", "feccia", "odio", "amore", "forzanuova", "forteprenestino", "nietsche", "ezrapound", "democrazia", "politica", "votare", "elezioni", "parlamento"], "time": 1509234711}
+{"actions": ["search_and_retweet"], "buddy": ["InfoAntifa", "LibreriAntigone", "romaoccupata", "Assospartaco", "BANDA_BASSOTTI", "rivamesta", "zeropregi", "progettoDegage", "contropiano", "DinamoPress", "ilmanifesto", "Radiondarossa", "repubblica", "notav_info", "Infoaut", "sap_clandestina", "zerocalcare", "FPrenestino", "AnpiRoma", "RFeminista_", "RomaAntifa", "AntifaOstia", "romattiva", "MilitantBlog", "RATM", "matteosalvinimi\u00a0", "gruppohobbit\u00a0", "CircoloFuturista", "MSR_cat\u00a0", "Occidentale", "OrdineNuovo", "romatoday\u00a0", "PBT_Torino", "Nigel_Farage", "UKIP", "SimoneCasaPound\u00a0", "MarcelloRuffo", "IannoneCpi", "ilgiornale\u00a0", "ChiaraScalzi85\u00a0", "BloccoStudentesco\u00a0", "prog_sociale", "ForzaNuova\u00a0", "AlbaDoratait\u00a0", "distefanoTW\u00a0", "CasaPoundItalia\u00a0", "giorgiameloni", "FratellidItalia"], "hash": ["fascismo", "antifascismo", "razzismo", "italia", "italiano", "italiaglitaliani", "stopinvasione", "puliziaetnica", "mussolini", "quandoceralui", "hitler", "farequadrato", "apologia", "nazismo", "antinazismo", "fakenews", "complotto", "noeuro", "scontri", "centrisociali", "occupazione", "lavoro", "sinistra", "manifestazione", "blackbloc", "vandalismo", "fanatismo", "destra", "parlamento", "violenza", "polizia", "esercito", "rom", "campirom", "roma", "guerra", "sciopero", "precari", "casa", "mafia", "camorra", "ndrangheta", "sindacato", "clandestino", "immigrato", "immigrati", "barconi", "negri", "cassazione", "pd", "leganord", "fdi", "an", "grillo", "m5s", "donne", "violenzasulledonne", "bambini", "famiglia", "dio", "patria", "difesa", "nazione", "paese", "madeinitaly", "salvini", "populismo", "casapound", "lepen", "schifo", "feccia", "odio", "amore", "forzanuova", "forteprenestino", "nietsche", "ezrapound", "democrazia", "politica", "votare", "elezioni", "parlamento"], "time": 1509234747}
+{"actions": ["search_and_retweet"], "buddy": ["InfoAntifa", "LibreriAntigone", "romaoccupata", "Assospartaco", "BANDA_BASSOTTI", "rivamesta", "zeropregi", "progettoDegage", "contropiano", "DinamoPress", "ilmanifesto", "Radiondarossa", "repubblica", "notav_info", "Infoaut", "sap_clandestina", "zerocalcare", "FPrenestino", "AnpiRoma", "RFeminista_", "RomaAntifa", "AntifaOstia", "romattiva", "MilitantBlog", "RATM", "matteosalvinimi\u00a0", "gruppohobbit\u00a0", "CircoloFuturista", "MSR_cat\u00a0", "Occidentale", "OrdineNuovo", "romatoday\u00a0", "PBT_Torino", "Nigel_Farage", "UKIP", "SimoneCasaPound\u00a0", "MarcelloRuffo", "IannoneCpi", "ilgiornale\u00a0", "ChiaraScalzi85\u00a0", "BloccoStudentesco\u00a0", "prog_sociale", "ForzaNuova\u00a0", "AlbaDoratait\u00a0", "distefanoTW\u00a0", "CasaPoundItalia\u00a0", "giorgiameloni", "FratellidItalia"], "hash": ["fascismo", "antifascismo", "razzismo", "italia", "italiano", "italiaglitaliani", "stopinvasione", "puliziaetnica", "mussolini", "quandoceralui", "hitler", "farequadrato", "apologia", "nazismo", "antinazismo", "fakenews", "complotto", "noeuro", "scontri", "centrisociali", "occupazione", "lavoro", "sinistra", "manifestazione", "blackbloc", "vandalismo", "fanatismo", "destra", "parlamento", "violenza", "polizia", "esercito", "rom", "campirom", "roma", "guerra", "sciopero", "precari", "casa", "mafia", "camorra", "ndrangheta", "sindacato", "clandestino", "immigrato", "immigrati", "barconi", "negri", "cassazione", "pd", "leganord", "fdi", "an", "grillo", "m5s", "donne", "violenzasulledonne", "bambini", "famiglia", "dio", "patria", "difesa", "nazione", "paese", "madeinitaly", "salvini", "populismo", "casapound", "lepen", "schifo", "feccia", "odio", "amore", "forzanuova", "forteprenestino", "nietsche", "ezrapound", "democrazia", "politica", "votare", "elezioni", "parlamento"], "time": 1509234854}
+{"actions": ["search_and_retweet"], "buddy": ["InfoAntifa", "LibreriAntigone", "romaoccupata", "Assospartaco", "BANDA_BASSOTTI", "rivamesta", "zeropregi", "progettoDegage", "contropiano", "DinamoPress", "ilmanifesto", "Radiondarossa", "repubblica", "notav_info", "Infoaut", "sap_clandestina", "zerocalcare", "FPrenestino", "AnpiRoma", "RFeminista_", "RomaAntifa", "AntifaOstia", "romattiva", "MilitantBlog", "RATM", "matteosalvinimi\u00a0", "gruppohobbit\u00a0", "CircoloFuturista", "MSR_cat\u00a0", "Occidentale", "OrdineNuovo", "romatoday\u00a0", "PBT_Torino", "Nigel_Farage", "UKIP", "SimoneCasaPound\u00a0", "MarcelloRuffo", "IannoneCpi", "ilgiornale\u00a0", "ChiaraScalzi85\u00a0", "BloccoStudentesco\u00a0", "prog_sociale", "ForzaNuova\u00a0", "AlbaDoratait\u00a0", "distefanoTW\u00a0", "CasaPoundItalia\u00a0", "giorgiameloni", "FratellidItalia"], "hash": ["fascismo", "antifascismo", "razzismo", "italia", "italiano", "italiaglitaliani", "stopinvasione", "puliziaetnica", "mussolini", "quandoceralui", "hitler", "farequadrato", "apologia", "nazismo", "antinazismo", "fakenews", "complotto", "noeuro", "scontri", "centrisociali", "occupazione", "lavoro", "sinistra", "manifestazione", "blackbloc", "vandalismo", "fanatismo", "destra", "parlamento", "violenza", "polizia", "esercito", "rom", "campirom", "roma", "guerra", "sciopero", "precari", "casa", "mafia", "camorra", "ndrangheta", "sindacato", "clandestino", "immigrato", "immigrati", "barconi", "negri", "cassazione", "pd", "leganord", "fdi", "an", "grillo", "m5s", "donne", "violenzasulledonne", "bambini", "famiglia", "dio", "patria", "difesa", "nazione", "paese", "madeinitaly", "salvini", "populismo", "casapound", "lepen", "schifo", "feccia", "odio", "amore", "forzanuova", "forteprenestino", "nietsche", "ezrapound", "democrazia", "politica", "votare", "elezioni", "parlamento"], "time": 1509234865}
+{"actions": ["search_and_retweet"], "buddy": ["InfoAntifa", "LibreriAntigone", "romaoccupata", "Assospartaco", "BANDA_BASSOTTI", "rivamesta", "zeropregi", "progettoDegage", "contropiano", "DinamoPress", "ilmanifesto", "Radiondarossa", "repubblica", "notav_info", "Infoaut", "sap_clandestina", "zerocalcare", "FPrenestino", "AnpiRoma", "RFeminista_", "RomaAntifa", "AntifaOstia", "romattiva", "MilitantBlog", "RATM", "matteosalvinimi\u00a0", "gruppohobbit\u00a0", "CircoloFuturista", "MSR_cat\u00a0", "Occidentale", "OrdineNuovo", "romatoday\u00a0", "PBT_Torino", "Nigel_Farage", "UKIP", "SimoneCasaPound\u00a0", "MarcelloRuffo", "IannoneCpi", "ilgiornale\u00a0", "ChiaraScalzi85\u00a0", "BloccoStudentesco\u00a0", "prog_sociale", "ForzaNuova\u00a0", "AlbaDoratait\u00a0", "distefanoTW\u00a0", "CasaPoundItalia\u00a0", "giorgiameloni", "FratellidItalia"], "hash": ["fascismo", "antifascismo", "razzismo", "italia", "italiano", "italiaglitaliani", "stopinvasione", "puliziaetnica", "mussolini", "quandoceralui", "hitler", "farequadrato", "apologia", "nazismo", "antinazismo", "fakenews", "complotto", "noeuro", "scontri", "centrisociali", "occupazione", "lavoro", "sinistra", "manifestazione", "blackbloc", "vandalismo", "fanatismo", "destra", "parlamento", "violenza", "polizia", "esercito", "rom", "campirom", "roma", "guerra", "sciopero", "precari", "casa", "mafia", "camorra", "ndrangheta", "sindacato", "clandestino", "immigrato", "immigrati", "barconi", "negri", "cassazione", "pd", "leganord", "fdi", "an", "grillo", "m5s", "donne", "violenzasulledonne", "bambini", "famiglia", "dio", "patria", "difesa", "nazione", "paese", "madeinitaly", "salvini", "populismo", "casapound", "lepen", "schifo", "feccia", "odio", "amore", "forzanuova", "forteprenestino", "nietsche", "ezrapound", "democrazia", "politica", "votare", "elezioni", "parlamento"], "time": 1509234890}
+{"actions": ["search_and_retweet"], "buddy": ["InfoAntifa", "LibreriAntigone", "romaoccupata", "Assospartaco", "BANDA_BASSOTTI", "rivamesta", "zeropregi", "progettoDegage", "contropiano", "DinamoPress", "ilmanifesto", "Radiondarossa", "repubblica", "notav_info", "Infoaut", "sap_clandestina", "zerocalcare", "FPrenestino", "AnpiRoma", "RFeminista_", "RomaAntifa", "AntifaOstia", "romattiva", "MilitantBlog", "RATM", "matteosalvinimi\u00a0", "gruppohobbit\u00a0", "CircoloFuturista", "MSR_cat\u00a0", "Occidentale", "OrdineNuovo", "romatoday\u00a0", "PBT_Torino", "Nigel_Farage", "UKIP", "SimoneCasaPound\u00a0", "MarcelloRuffo", "IannoneCpi", "ilgiornale\u00a0", "ChiaraScalzi85\u00a0", "BloccoStudentesco\u00a0", "prog_sociale", "ForzaNuova\u00a0", "AlbaDoratait\u00a0", "distefanoTW\u00a0", "CasaPoundItalia\u00a0", "giorgiameloni", "FratellidItalia"], "hash": ["fascismo", "antifascismo", "razzismo", "italia", "italiano", "italiaglitaliani", "stopinvasione", "puliziaetnica", "mussolini", "quandoceralui", "hitler", "farequadrato", "apologia", "nazismo", "antinazismo", "fakenews", "complotto", "noeuro", "scontri", "centrisociali", "occupazione", "lavoro", "sinistra", "manifestazione", "blackbloc", "vandalismo", "fanatismo", "destra", "parlamento", "violenza", "polizia", "esercito", "rom", "campirom", "roma", "guerra", "sciopero", "precari", "casa", "mafia", "camorra", "ndrangheta", "sindacato", "clandestino", "immigrato", "immigrati", "barconi", "negri", "cassazione", "pd", "leganord", "fdi", "an", "grillo", "m5s", "donne", "violenzasulledonne", "bambini", "famiglia", "dio", "patria", "difesa", "nazione", "paese", "madeinitaly", "salvini", "populismo", "casapound", "lepen", "schifo", "feccia", "odio", "amore", "forzanuova", "forteprenestino", "nietsche", "ezrapound", "democrazia", "politica", "votare", "elezioni", "parlamento"], "time": 1509234992}
+{"actions": ["search_and_retweet"], "buddy": ["InfoAntifa", "LibreriAntigone", "romaoccupata", "Assospartaco", "BANDA_BASSOTTI", "rivamesta", "zeropregi", "progettoDegage", "contropiano", "DinamoPress", "ilmanifesto", "Radiondarossa", "repubblica", "notav_info", "Infoaut", "sap_clandestina", "zerocalcare", "FPrenestino", "AnpiRoma", "RFeminista_", "RomaAntifa", "AntifaOstia", "romattiva", "MilitantBlog", "RATM", "matteosalvinimi\u00a0", "gruppohobbit\u00a0", "CircoloFuturista", "MSR_cat\u00a0", "Occidentale", "OrdineNuovo", "romatoday\u00a0", "PBT_Torino", "Nigel_Farage", "UKIP", "SimoneCasaPound\u00a0", "MarcelloRuffo", "IannoneCpi", "ilgiornale\u00a0", "ChiaraScalzi85\u00a0", "BloccoStudentesco\u00a0", "prog_sociale", "ForzaNuova\u00a0", "AlbaDoratait\u00a0", "distefanoTW\u00a0", "CasaPoundItalia\u00a0", "giorgiameloni", "FratellidItalia"], "hash": ["fascismo", "antifascismo", "razzismo", "italia", "italiano", "italiaglitaliani", "stopinvasione", "puliziaetnica", "mussolini", "quandoceralui", "hitler", "farequadrato", "apologia", "nazismo", "antinazismo", "fakenews", "complotto", "noeuro", "scontri", "centrisociali", "occupazione", "lavoro", "sinistra", "manifestazione", "blackbloc", "vandalismo", "fanatismo", "destra", "parlamento", "violenza", "polizia", "esercito", "rom", "campirom", "roma", "guerra", "sciopero", "precari", "casa", "mafia", "camorra", "ndrangheta", "sindacato", "clandestino", "immigrato", "immigrati", "barconi", "negri", "cassazione", "pd", "leganord", "fdi", "an", "grillo", "m5s", "donne", "violenzasulledonne", "bambini", "famiglia", "dio", "patria", "difesa", "nazione", "paese", "madeinitaly", "salvini", "populismo", "casapound", "lepen", "schifo", "feccia", "odio", "amore", "forzanuova", "forteprenestino", "nietsche", "ezrapound", "democrazia", "politica", "votare", "elezioni", "parlamento"], "time": 1509235079}
+{"actions": ["search_and_retweet"], "buddy": ["InfoAntifa", "LibreriAntigone", "romaoccupata", "Assospartaco", "BANDA_BASSOTTI", "rivamesta", "zeropregi", "progettoDegage", "contropiano", "DinamoPress", "ilmanifesto", "Radiondarossa", "repubblica", "notav_info", "Infoaut", "sap_clandestina", "zerocalcare", "FPrenestino", "AnpiRoma", "RFeminista_", "RomaAntifa", "AntifaOstia", "romattiva", "MilitantBlog", "RATM", "matteosalvinimi\u00a0", "gruppohobbit\u00a0", "CircoloFuturista", "MSR_cat\u00a0", "Occidentale", "OrdineNuovo", "romatoday\u00a0", "PBT_Torino", "Nigel_Farage", "UKIP", "SimoneCasaPound\u00a0", "MarcelloRuffo", "IannoneCpi", "ilgiornale\u00a0", "ChiaraScalzi85\u00a0", "BloccoStudentesco\u00a0", "prog_sociale", "ForzaNuova\u00a0", "AlbaDoratait\u00a0", "distefanoTW\u00a0", "CasaPoundItalia\u00a0", "giorgiameloni", "FratellidItalia"], "hash": ["fascismo", "antifascismo", "razzismo", "italia", "italiano", "italiaglitaliani", "stopinvasione", "puliziaetnica", "mussolini", "quandoceralui", "hitler", "farequadrato", "apologia", "nazismo", "antinazismo", "fakenews", "complotto", "noeuro", "scontri", "centrisociali", "occupazione", "lavoro", "sinistra", "manifestazione", "blackbloc", "vandalismo", "fanatismo", "destra", "parlamento", "violenza", "polizia", "esercito", "rom", "campirom", "roma", "guerra", "sciopero", "precari", "casa", "mafia", "camorra", "ndrangheta", "sindacato", "clandestino", "immigrato", "immigrati", "barconi", "negri", "cassazione", "pd", "leganord", "fdi", "an", "grillo", "m5s", "donne", "violenzasulledonne", "bambini", "famiglia", "dio", "patria", "difesa", "nazione", "paese", "madeinitaly", "salvini", "populismo", "casapound", "lepen", "schifo", "feccia", "odio", "amore", "forzanuova", "forteprenestino", "nietsche", "ezrapound", "democrazia", "politica", "votare", "elezioni", "parlamento"], "time": 1509235175}
+{"actions": ["search_and_retweet"], "buddy": ["InfoAntifa", "LibreriAntigone", "romaoccupata", "Assospartaco", "BANDA_BASSOTTI", "rivamesta", "zeropregi", "progettoDegage", "contropiano", "DinamoPress", "ilmanifesto", "Radiondarossa", "repubblica", "notav_info", "Infoaut", "sap_clandestina", "zerocalcare", "FPrenestino", "AnpiRoma", "RFeminista_", "RomaAntifa", "AntifaOstia", "romattiva", "MilitantBlog", "RATM", "matteosalvinimi\u00a0", "gruppohobbit\u00a0", "CircoloFuturista", "MSR_cat\u00a0", "Occidentale", "OrdineNuovo", "romatoday\u00a0", "PBT_Torino", "Nigel_Farage", "UKIP", "SimoneCasaPound\u00a0", "MarcelloRuffo", "IannoneCpi", "ilgiornale\u00a0", "ChiaraScalzi85\u00a0", "BloccoStudentesco\u00a0", "prog_sociale", "ForzaNuova\u00a0", "AlbaDoratait\u00a0", "distefanoTW\u00a0", "CasaPoundItalia\u00a0", "giorgiameloni", "FratellidItalia"], "hash": ["fascismo", "antifascismo", "razzismo", "italia", "italiano", "italiaglitaliani", "stopinvasione", "puliziaetnica", "mussolini", "quandoceralui", "hitler", "farequadrato", "apologia", "nazismo", "antinazismo", "fakenews", "complotto", "noeuro", "scontri", "centrisociali", "occupazione", "lavoro", "sinistra", "manifestazione", "blackbloc", "vandalismo", "fanatismo", "destra", "parlamento", "violenza", "polizia", "esercito", "rom", "campirom", "roma", "guerra", "sciopero", "precari", "casa", "mafia", "camorra", "ndrangheta", "sindacato", "clandestino", "immigrato", "immigrati", "barconi", "negri", "cassazione", "pd", "leganord", "fdi", "an", "grillo", "m5s", "donne", "violenzasulledonne", "bambini", "famiglia", "dio", "patria", "difesa", "nazione", "paese", "madeinitaly", "salvini", "populismo", "casapound", "lepen", "schifo", "feccia", "odio", "amore", "forzanuova", "forteprenestino", "nietsche", "ezrapound", "democrazia", "politica", "votare", "elezioni", "parlamento"], "time": 1509235215}
+{"actions": ["search_and_retweet"], "buddy": ["InfoAntifa", "LibreriAntigone", "romaoccupata", "Assospartaco", "BANDA_BASSOTTI", "rivamesta", "zeropregi", "progettoDegage", "contropiano", "DinamoPress", "ilmanifesto", "Radiondarossa", "repubblica", "notav_info", "Infoaut", "sap_clandestina", "zerocalcare", "FPrenestino", "AnpiRoma", "RFeminista_", "RomaAntifa", "AntifaOstia", "romattiva", "MilitantBlog", "RATM", "matteosalvinimi\u00a0", "gruppohobbit\u00a0", "CircoloFuturista", "MSR_cat\u00a0", "Occidentale", "OrdineNuovo", "romatoday\u00a0", "PBT_Torino", "Nigel_Farage", "UKIP", "SimoneCasaPound\u00a0", "MarcelloRuffo", "IannoneCpi", "ilgiornale\u00a0", "ChiaraScalzi85\u00a0", "BloccoStudentesco\u00a0", "prog_sociale", "ForzaNuova\u00a0", "AlbaDoratait\u00a0", "distefanoTW\u00a0", "CasaPoundItalia\u00a0", "giorgiameloni", "FratellidItalia"], "hash": ["fascismo", "antifascismo", "razzismo", "italia", "italiano", "italiaglitaliani", "stopinvasione", "puliziaetnica", "mussolini", "quandoceralui", "hitler", "farequadrato", "apologia", "nazismo", "antinazismo", "fakenews", "complotto", "noeuro", "scontri", "centrisociali", "occupazione", "lavoro", "sinistra", "manifestazione", "blackbloc", "vandalismo", "fanatismo", "destra", "parlamento", "violenza", "polizia", "esercito", "rom", "campirom", "roma", "guerra", "sciopero", "precari", "casa", "mafia", "camorra", "ndrangheta", "sindacato", "clandestino", "immigrato", "immigrati", "barconi", "negri", "cassazione", "pd", "leganord", "fdi", "an", "grillo", "m5s", "donne", "violenzasulledonne", "bambini", "famiglia", "dio", "patria", "difesa", "nazione", "paese", "madeinitaly", "salvini", "populismo", "casapound", "lepen", "schifo", "feccia", "odio", "amore", "forzanuova", "forteprenestino", "nietsche", "ezrapound", "democrazia", "politica", "votare", "elezioni", "parlamento"], "time": 1509235242}
+{"actions": ["search_and_retweet"], "buddy": ["InfoAntifa", "LibreriAntigone", "romaoccupata", "Assospartaco", "BANDA_BASSOTTI", "rivamesta", "zeropregi", "progettoDegage", "contropiano", "DinamoPress", "ilmanifesto", "Radiondarossa", "repubblica", "notav_info", "Infoaut", "sap_clandestina", "zerocalcare", "FPrenestino", "AnpiRoma", "RFeminista_", "RomaAntifa", "AntifaOstia", "romattiva", "MilitantBlog", "RATM", "matteosalvinimi\u00a0", "gruppohobbit\u00a0", "CircoloFuturista", "MSR_cat\u00a0", "Occidentale", "OrdineNuovo", "romatoday\u00a0", "PBT_Torino", "Nigel_Farage", "UKIP", "SimoneCasaPound\u00a0", "MarcelloRuffo", "IannoneCpi", "ilgiornale\u00a0", "ChiaraScalzi85\u00a0", "BloccoStudentesco\u00a0", "prog_sociale", "ForzaNuova\u00a0", "AlbaDoratait\u00a0", "distefanoTW\u00a0", "CasaPoundItalia\u00a0", "giorgiameloni", "FratellidItalia"], "hash": ["fascismo", "antifascismo", "razzismo", "italia", "italiano", "italiaglitaliani", "stopinvasione", "puliziaetnica", "mussolini", "quandoceralui", "hitler", "farequadrato", "apologia", "nazismo", "antinazismo", "fakenews", "complotto", "noeuro", "scontri", "centrisociali", "occupazione", "lavoro", "sinistra", "manifestazione", "blackbloc", "vandalismo", "fanatismo", "destra", "parlamento", "violenza", "polizia", "esercito", "rom", "campirom", "roma", "guerra", "sciopero", "precari", "casa", "mafia", "camorra", "ndrangheta", "sindacato", "clandestino", "immigrato", "immigrati", "barconi", "negri", "cassazione", "pd", "leganord", "fdi", "an", "grillo", "m5s", "donne", "violenzasulledonne", "bambini", "famiglia", "dio", "patria", "difesa", "nazione", "paese", "madeinitaly", "salvini", "populismo", "casapound", "lepen", "schifo", "feccia", "odio", "amore", "forzanuova", "forteprenestino", "nietsche", "ezrapound", "democrazia", "politica", "votare", "elezioni", "parlamento"], "time": 1509235254}

+ 3 - 0
requirements.txt

@@ -0,0 +1,3 @@
+tweepy
+pymongo
+logging

+ 37 - 0
setup.py

@@ -0,0 +1,37 @@
+import os
+
+from setuptools import setup
+
+
+def read(fname):
+    with open(os.path.join(os.path.dirname(__file__), fname)) as buf:
+        return buf.read()
+
+
+conf = dict(
+        name='valeriovive',
+        version='0.1',
+        description='Twitter Filter Bubble Experiment',
+        long_description=read('README.md'),
+        author='cocconat',
+        author_email='g3-3k@paranoici.org',
+        url='https://github.com/g3-3k/valeriovive',
+        license='AGPL',
+        packages=['valeriovive'],
+        install_requires=[
+            'tweepy',
+            'pymongo',
+            'mutagen',
+            'logging',
+        ],
+        zip_safe=False,
+
+        classifiers=[
+          "License :: OSI Approved :: GNU Affero General Public License v3",
+          "Operating System :: POSIX :: Linux",
+          "Programming Language :: Python :: 2",
+        ])
+
+
+if __name__ == '__main__':
+    setup(**conf)

BIN
valeriovive/.twitter_agent.py.swp


+ 6 - 0
valeriovive/__init__.py

@@ -0,0 +1,6 @@
+
+from .experiment import Experiment
+from .nano import Nano
+from .twitter_agent import TwitterAgent
+from .scheduler import Scheduler, dict_from_json
+from .daemon import Daemon

+ 52 - 0
valeriovive/__main__.py

@@ -0,0 +1,52 @@
+import logging
+from experiment import ExperimentDaemon, Experiment, ExperimentDebug, ExperimentShell
+import sys,argparse, os
+
+def getparser():
+        parser = argparse.ArgumentParser(description='run TIBER instance')
+        parser.add_argument('-c','--conf',dest='conf_file', type=str, default=None,
+                            help='configuration_file for the experiment')
+        parser.add_argument('--start', dest='start', action='store_true', default=False,
+                    help='start valeriovive ')
+        parser.add_argument('--restart', dest='restart', action='store_true',default=False,
+                    help='restart valeriovive ')
+        parser.add_argument('--stop', dest='stop', action='store_true',default=False,
+                    help='stop valeriovive ')
+        parser.add_argument('--oneshot', dest='oneshot', action='store_true',default=False,
+                    help='do one shot twitter action ')
+        parser.add_argument('--debug', dest='debug', action='store_true',default=False,
+                    help='get object in ipython console')
+        parser.add_argument('--remove-friends', dest='remove_friends', action='store_true',default=False,
+                    help='remove all following accounts')
+        parser.add_argument('--shell', dest='shell', action='store_true',default=False,
+                    help='open a shell')
+        return parser.parse_args()
+
+
+if __name__ == "__main__":
+    logging_path=os.path.join(os.getcwd(),'valeriovive/logging.ini')
+    logging.config.fileConfig(logging_path)
+    args = getparser()
+    if args.debug or args.oneshot:
+        exp=ExperimentDebug(args)
+    elif args.shell:
+        print("entering shell!")
+        exp=ExperimentShell()
+    elif args.start:
+        exp=ExperimentDaemon("/tmp/valeriovive.pid", args)
+        exp.start()
+        sys.exit(0)
+    elif args.restart:
+        exp=ExperimentDaemon("/tmp/valeriovive.pid", args)
+        exp.restart()
+        sys.exit(0)
+    elif args.stop:
+        exp=ExperimentDaemon("/tmp/valeriovive.pid", args)
+        exp.stop()
+        sys.exit(0)
+    else:
+        print ("usage: %s start|stop|restart" % sys.argv[0])
+        sys.exit(2)
+
+
+

BIN
valeriovive/__pycache__/__init__.cpython-36.pyc


BIN
valeriovive/__pycache__/__main__.cpython-36.pyc


BIN
valeriovive/__pycache__/daemon.cpython-36.pyc


BIN
valeriovive/__pycache__/experiment.cpython-36.pyc


BIN
valeriovive/__pycache__/nano.cpython-36.pyc


BIN
valeriovive/__pycache__/scheduler.cpython-36.pyc


BIN
valeriovive/__pycache__/twitter_agent.cpython-36.pyc


+ 138 - 0
valeriovive/daemon.py

@@ -0,0 +1,138 @@
+#!/usr/bin/env python
+# This class contains the class for the Linux system daemon.
+
+
+import sys, os, time, atexit
+from signal import SIGTERM
+import logging
+class Daemon:
+    """
+    A generic daemon class.
+
+    Usage: subclass the Daemon class and override the run() method
+    """
+    def __init__(self, pidfile, args, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
+        self.stdin = stdin
+        self.stdout = stdout
+        self.stderr = stderr
+        self.pidfile = pidfile
+        self.args   = args
+        self.log = logging.getLogger("daemon")
+
+
+    def daemonize(self):
+            """
+            do the UNIX double-fork magic, see Stevens' "Advanced
+            Programming in the UNIX Environment" for details (ISBN 0201563177)
+            http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
+            """
+            try:
+                    pid = os.fork()
+                    if pid > 0:
+                            # exit first parent
+                            sys.exit(0)
+            except OSError as e:
+                    self.log.error("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
+                    sys.exit(1)
+
+            # decouple from parent environment
+            ex_path=os.getcwd()
+            os.chdir("/")
+            os.setsid()
+            os.umask(0)
+
+            # do second fork
+            try:
+                    pid = os.fork()
+                    if pid > 0:
+                            # exit from second parent
+                            sys.exit(0)
+            except OSError as e:
+                    self.log.error("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
+                    sys.exit(1)
+
+#             # redirect standard file descriptors
+            # sys.stdout.flush()
+            # sys.stderr.flush()
+            # si = file(self.stdin, 'r')
+            # so = file(self.stdout, 'a+')
+            # se = file(self.stderr, 'a+', 0)
+            # os.dup2(si.fileno(), sys.stdin.fileno())
+            # os.dup2(so.fileno(), sys.stdout.fileno())
+            # os.dup2(se.fileno(), sys.stderr.fileno())
+
+            # write pidfile
+            atexit.register(self.delpid)
+            pid = str(os.getpid())
+            open(self.pidfile,'w+').write("%s\n" % pid)
+            os.chdir(ex_path)
+
+    def delpid(self):
+            os.remove(self.pidfile)
+
+    def start(self):
+            """
+            Start the daemon
+            """
+            self.log.debug("daemon started")
+            # Check for a pidfile to see if the daemon already runs
+            try:
+                    pf = open(self.pidfile,'r')
+                    pid = int(pf.read().strip())
+                    pf.close()
+            except IOError:
+                    pid = None
+
+            if pid:
+                    message = "pidfile %s already exist. Daemon already running?\n"
+                    sys.stderr.write(message % self.pidfile)
+                    sys.exit(1)
+
+            # Start the daemon
+            self.daemonize()
+            self.run()
+
+    def stop(self):
+            """
+            Stop the daemon
+            """
+            self.log.debug("daemon stopped   ")
+            # Get the pid from the pidfile
+            try:
+                    pf = open(self.pidfile,'r')
+                    pid = int(pf.read().strip())
+                    pf.close()
+            except IOError:
+                    pid = None
+
+            if not pid:
+                    message = "pidfile %s does not exist. Daemon not running?\n"
+                    sys.stderr.write(message % self.pidfile)
+                    return # not an error in a restart
+
+            # Try killing the daemon process
+            try:
+                    while 1:
+                            os.kill(pid, SIGTERM)
+                            time.sleep(0.1)
+            except OSError as err:
+                    err = str(err)
+                    if err.find("No such process") > 0:
+                            if os.path.exists(self.pidfile):
+                                    os.remove(self.pidfile)
+                    else:
+                            print (str(err))
+                            sys.exit(1)
+
+    def restart(self):
+            """
+            Restart the daemon
+            """
+            self.stop()
+            self.start()
+
+    def run(self):
+            """
+            You should override this method when you subclass Daemon. It will be called after the process has been
+            daemonized by start() or restart().
+            """

+ 31 - 0
valeriovive/database.py

@@ -0,0 +1,31 @@
+import json
+
+class DB(object):
+    '''
+    db.add({timestamp: time.time(),
+    agent: 'tizio',
+    action: 'search',
+    target: 'tasse'
+    })
+    db.add({timestamp: time.time(),
+    agent: 'tizio',
+    action: 'wall',
+    seen: [
+    {user: 'zerogreggi', msg: 'ho le pecore'},
+    {user: 'caio', msg: 'ci faccio il formaggio'},
+    ]
+    })
+    searches = [s for s in db.all() if s['action'] == 'wall']
+    '''
+    def __init__(self, fname):
+        self.fname = fname
+
+    def add(self, doc):
+        with open(self.fname, 'a') as buf:
+            buf.write(json.dumps(doc))
+            buf.write('\n')
+
+    def all(self):
+        with open(self.fname) as buf:
+            for line in buf:
+                yield json.loads(line)

+ 134 - 0
valeriovive/experiment.py

@@ -0,0 +1,134 @@
+import sys
+import logging
+from valeriovive.nano import Nano
+from valeriovive.scheduler import Scheduler,dict_from_json
+
+import logging.config
+import sys, time, os
+from valeriovive.daemon import Daemon
+
+#!/usr/bin/env python
+
+
+class ExperimentDaemon(Daemon):
+    def run(self):
+        experiment=Experiment(self.args)
+        experiment.start_experiment()
+
+def ExperimentShell():
+    Experiment.run_shell()
+
+
+def ExperimentDebug(args):
+    experiment=Experiment(args)
+    experiment.oneshot()
+
+class Experiment(Scheduler):
+    """
+    Experiment classs
+    controls the evolution of the experiment with the Scheduler
+    Each parameter can be set through this class
+    As many config file as many bots will be created, the bot are stored
+    in the 'bots' attribute.
+    """
+    def __init__(self,*args, **kwargs):
+        self.log = logging.getLogger("root")
+        Scheduler.__init__(self, self.events_manager)
+        self.bots=[]
+        if "conf" in kwargs:
+            self.prepare_experiment(kwargs["conf"])
+        if "remove_friends" in kwargs:
+            self.remove_friends=True
+        self.log.debug("Experiment configured with {}".format(self.conf_file ))
+
+
+    @classmethod
+    def create_experiment(cls, **kwargs):
+        return Experiment(kwargs)
+
+
+    """
+    Prepare experiment with conf_file params
+    """
+    def prepare_experiment(self, conf_file=None):
+
+        ##set the conf file or use the default
+        if isinstance(conf_file, str):
+            self.conf = dict_from_json(conf_file)
+            self.conf_file = os.path.join(os.getcwd(),conf_file)
+        else:
+            self.log.error("if you re not setting conf file, you are wrong")
+            self.conf_file = os.path.join(os.getcwd(),'valeriovive/nani.json')
+            self.conf = dict_from_json(self.conf_file)
+            self.log.debug("conf file is {}".format(self.conf_file))
+
+        ##pass the conf file to each agent
+        for agent in self.conf['agents']:
+            nano = Nano(agent, self.conf_file)
+            self.bots.append(nano)
+
+    @staticmethod
+    def run_shell():
+        settings={}
+
+        while True:
+            s = input()
+            if s == "start":
+                exp = Experiment.create_experiment(settings)
+            elif s == "set conf":
+                print("digit the path to conf file")
+                conf_path = input()
+                try:
+                    settings["conf"]=conf_path
+                except:
+                    print("set configuration failed")
+            elif s == "remove friends":
+               settings["remove_friends"]=True
+            elif s == "exit" or s == "quit" or s == "q":
+                # break
+
+    def start_experiment(self, duration=0):
+        '''
+        Start the experiment.
+        Argument:
+        duration -- expressed in seconds
+        if duration not set, it will continue indefinitely
+        '''
+        self.log.debug("Experiment routine starting")
+        self.routine_manager(self.conf_file)
+
+    def oneshot(self):
+        """
+        Play one only experience for the bot"
+        """
+        self.log.debug("Experiment one shot")
+        for nano in self.bots:
+            if self.remove_friends:
+                nano.remove_friends()
+            else:
+                nano.set_behaviour()
+                nano.online_experience()
+
+    @property
+    def common_hours(self):
+        return self.conf['common']['hours']
+
+    def events_manager(self):
+        """
+        Do the relevant action for the experiment:
+        1) For each nano, at scheduled time, start online experience
+        """
+        for nano in self.bots:
+            nano.set_behaviour()
+            ##retrieve action hours
+            try:
+                nano.events = Scheduler.events_from_hours(nano.get_hours())
+            except:
+                nano.events = Scheduler.events_from_hours(self.common_hours)
+            ##schedule actions
+            for event_time in nano.events:
+                self.schedule_event(event_time, nano.online_experience)
+                logging.debug("nano {} scheduled at {}".format(nano.name, str(event_time)))
+
+
+

+ 39 - 0
valeriovive/logging.ini

@@ -0,0 +1,39 @@
+[loggers]
+keys=root
+
+[handlers]
+keys=consoleHandler
+
+[formatters]
+keys=simpleFormatter
+
+[logger_root]
+level=DEBUG
+handlers=consoleHandler
+
+[logger_scheduler]
+level=DEBUG
+handlers=consoleHandler
+
+[logger_daemon]
+level=DEBUG
+handlers=consoleHandler
+
+[logger_twitter_agent]
+level=DEBUG
+handlers=consoleHandler
+
+[logger_nano]
+level=DEBUG
+handlers=consoleHandler
+
+[handler_consoleHandler]
+class=StreamHandler
+level=DEBUG
+formatter=simpleFormatter
+args=(sys.stdout,)
+
+[formatter_simpleFormatter]
+format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
+datefmt=
+

+ 31 - 0
valeriovive/nani.json

@@ -0,0 +1,31 @@
+{"agents":["sbinzolo"],
+"individual_behaviour":false,
+"sbinzolo":{
+      "name":"sbinzolo",
+      "dbpath": "sbinzolo.db",
+      "twitter":{
+      "consumer_key":"wG4qh5Uu9WAJiJAtYHEOUoTPd",
+      "consumer_set":"lR9mCtErxJ1rWwNaR9RtvpmSsKs301qxvwCt0658CUjAkydMXx",
+      "access_token":"863857515276230657-UajuyvISnw8537s8lXUBLI8h2zudpYR",
+      "secret_token":"UMBh1YFokq85Sl48FTFl0V4fJa7vBhwViyta8KOpe5lCq"
+       },
+      "actions":["search_and_retweet","search_and_follow","retweet_my_friends"],
+      "buddies":["Leila","Armando","FortePrenestino"],
+      "hashtags":["fasciappesi","cazziemazzi","giuliascopa"],
+      "hours":[0, 10, 17, 23]
+},
+"common":{
+       "actions":["search_and_retweet","search_and_follow","retweet_my_friends"],
+       "buddies":["Leila","Armando","FortePrenestino"],
+       "hashtags":["fasciappesi","cazziemazzi","giuliascopa"],
+       "hours":[0, 10, 17, 23],
+       "end_date":"2020-04-03",
+       "scheduler_interval":"midnight",
+       "buddies" : [
+"InfoAntifa","LibreriAntigone","romaoccupata","Assospartaco","BANDA_BASSOTTI","rivamesta","zeropregi","progettoDegage","contropiano","DinamoPress","ilmanifesto","Radiondarossa","repubblica","notav_info","Infoaut","sap_clandestina","zerocalcare","FPrenestino","AnpiRoma","RFeminista_","RomaAntifa",
+"AntifaOstia","romattiva","MilitantBlog","RATM","matteosalvinimi ","gruppohobbit ","CircoloFuturista","MSR_cat ","Occidentale","OrdineNuovo","romatoday ","PBT_Torino ","Nigel_Farage ","UKIP”,”SimoneCasaPound ","MarcelloRuffo ","IannoneCpi ","ilgiornale ","ChiaraScalzi85 ","BloccoStudentesco ","prog_sociale","ForzaNuova ","AlbaDoratait ","distefanoTW ","CasaPoundItalia ","giorgiameloni","FratellidItalia"],
+
+       "hashtags" : ["fascismo","antifascismo","razzismo","italia","italiano","italiaglitaliani","stopinvasione","puliziaetnica","mussolini","quandoceralui","hitler","farequadrato","apologia","nazismo","antinazismo","fakenews","complotto","noeuro","scontri","centrisociali","occupazione","lavoro","sinistra","manifestazione","blackbloc","vandalismo","fanatismo","destra","parlamento","violenza","polizia","esercito","rom","campirom","roma","guerra","sciopero","precari","casa","mafia","camorra","ndrangheta","sindacato","clandestino","immigrato","immigrati","barconi","negri","cassazione","pd","leganord","fdi","an","grillo","m5s","donne","violenzasulledonne","bambini","famiglia","dio","patria","difesa","nazione","paese","madeinitaly","salvini","populismo","casapound","lepen","schifo","feccia","odio","amore","forzanuova","forteprenestino","nietsche","ezrapound","democrazia","politica","votare","elezioni","parlamento"]
+}
+}
+

+ 134 - 0
valeriovive/nano.py

@@ -0,0 +1,134 @@
+from valeriovive.twitter_agent import TwitterAgent
+import  random
+import json
+import logging
+import time
+from valeriovive.scheduler import dict_from_json
+
+
+class Nano:
+    '''
+    Create Nano Object
+    Nano is the active element of the experiment,it does stuff
+    Nano remains during all the experiment.
+    Nano is actually the bot and will be initialited with conf.file path. That cannot change.
+    Nano has no perception of time.
+
+    Attributes
+    ==========
+    CONF:
+    common_conf dict  See README
+    own_conf    dict  See README
+
+    __twitter_agent TwitterAgent(Tweepy)
+
+    Behaviour:
+    actions         set of __twitter agent methods
+    buddy_list      list(strigs)
+    hash_list
+    events          list(hours(int[0-23]))
+
+    Methods
+    ===========
+
+
+    '''
+    def __init__(self, name, conf_file):
+        self.name=name
+        self.conf_file=conf_file
+        self.twitter_agent = TwitterAgent(name,dict_from_json(self.conf_file)[self.name]["twitter"])
+        self.actions =[]
+        ###
+        self.buddy_list = []
+        self.hash_list  = []
+        self.actions_list =[]
+
+        self.events=None
+
+        ### loggers
+        self.logger = logging.getLogger(name)
+        self.logger.info('created Nano {} obj, and file {}'.format(self.name,conf_file))
+
+    @property
+    def conf(self):
+        return dict_from_json(self.conf_file)[self.name]
+
+    # def twitter_conf(conf_file):
+        # try:
+            # return dict_from_json(conf_file)[self.name]["twitter"]
+        # except KeyError:
+            # raise ValueError("missing twitter conf in the configuration file")
+    """
+    Set behaviour
+
+    Dict needs to contain buddies , hashtags , actions
+    """
+    def set_behaviour(self):
+        if self.buddy_list == dict_from_json(self.conf_file)["individual_behaviour"]:
+            self.buddy_list = dict_from_json(self.conf_file)[self.name]['buddies']
+            self.hash_list  = dict_from_json(self.conf_file)[self.name]['hashtags']
+            self.actions_list    = dict_from_json(self.conf_file)[self.name]['actions']
+        else:
+            self.buddy_list = dict_from_json(self.conf_file)["common"]['buddies']
+            self.hash_list  = dict_from_json(self.conf_file)["common"]['hashtags']
+            self.actions_list    = dict_from_json(self.conf_file)["common"]['actions']
+        self.logger.debug("buddies: {} \n, hashtags: {} \n, actions: {}\n".format(self.buddy_list,self.hash_list,self.actions_list))
+        self.get_actions()
+
+    def get_hours(self):
+        return dict_from_json(self.conf_file[self.name]['hours'])
+
+    def get_actions(self):
+        """
+        Retrieve functions from config and add to actions_list
+        """
+        self.actions=[]
+        if "search_and_follow" in self.actions_list:
+            self.actions.append(self.twitter_agent.search_and_follow)
+        if "search_and_retweet" in self.actions_list:
+            self.actions.append(self.twitter_agent.search_and_retweet)
+        if "get_user_timeline" in self.actions_list:
+            self.actions.append(self.twitter_agent.get_user_timeline)
+        if "destroy_all_friends" in self.actions_list:
+            self.actions.append(self.twitter_agent.destroy_all_friends)
+
+        # if "retweet_my_friends" in self.actions:
+            # self.actions.append(self.__twitter_agent.retweet_my_friends)
+
+    """
+    Start Online Session
+    log with tweepy and do stuff as in behaviour
+    """
+    def online_experience(self):
+        random.shuffle(self.actions)
+        self.twitter_agent.connect()
+        if not self.twitter_agent.connected:
+            self.logger.error("cannot connect to Twitter!")
+            return
+        # self.twitter_agent.get_user_timeline()
+        for action in self.actions:
+            self.logger.debug("next action is {}".format(action.__name__))
+            try:
+                action(self.buddy_list, self.hash_list)
+            except :
+                self.logger.exception("Action {} failed".format(action.__name__))
+        if 'dbpath' in self.conf:
+            with open(self.conf['dbpath'], 'a') as buf:
+                record = {}
+                record['actions'] = [a.__name__ for a in self.actions]
+                record['buddy']= self.buddy_list
+                record['hash'] = self.hash_list
+                record['time'] = int(time.time())
+                buf.write(json.dumps(record))
+                buf.write("\n")
+
+    def remove_friends(self):
+        self.twitter_agent.connect()
+        try:
+            self.twitter_agent.destroy_all_friends()
+        except :
+            self.logger.error("cannot connect to Twitter!")
+
+
+
+

+ 0 - 0
valeriovive/nanoBot.sh


+ 77 - 0
valeriovive/scheduler.py

@@ -0,0 +1,77 @@
+import json, sched, datetime, time
+import logging
+import threading
+import random
+
+def dict_from_json(json_file):
+        with open(json_file) as json_data:
+            dict_ = json.load(json_data)
+        return dict_
+
+class Scheduler:
+    def __init__(self, events_manager):
+        self.log = logging.getLogger(__name__)
+        self.log.info(" starting {} ".format(__name__))
+        self.events = []
+        self.hours = []
+        self.events_manager = events_manager
+
+    """
+    Converts hours in dates.
+    Every day convert the hour in the exact date yyyy-mm-dd hh-mm
+    """
+    @staticmethod
+    def events_from_hours(hours):
+        if not isinstance(hours, list):
+            hours = list(hours)
+        events = [datetime.datetime.today().replace(hour=hour,
+                                                    minute=random.choice(range(60)))
+                                                    for hour in hours]
+        return events
+
+    def routine_manager(self, conf_file):
+        """
+        Routine manager
+        Always running untill --stop
+        conf_file is a path to json file.
+        The configuration file is read continously
+        """
+        try:
+            logging.info("routine manager start at {}".format(str(datetime.datetime.now())))
+            conf = dict_from_json(conf_file)['common']
+        except:
+            self.log.error(conf_file+ " is the wrong configuration file")
+        while True and datetime.datetime.now() < datetime.datetime.strptime(conf["end_date"],"%Y-%m-%d"):
+            self.events_manager()
+            self.log.debug("routine manager loop at {}".format(str(datetime.datetime.now())))
+            conf = dict_from_json(conf_file)['common']
+            try:
+                if conf["scheduler_interval"] == "midnight":
+                    interval_seconds = (datetime.datetime.today().replace(hour=23, minute=59) - datetime.datetime.now()).total_seconds()
+                    self.log.info("Next routine_manager loop at {}".format(datetime.datetime.today().replace(hour=23, minute=59)))
+                if isinstance(conf["scheduler_interval"], int):
+                    interval_seconds = datetime.timedelta(hours=conf["scheduler_interval"])
+            except KeyError:
+                self.log.error("Scheduler properties not found in {}", conf_file)
+            time.sleep(interval_seconds)
+
+    @staticmethod
+    def schedule_event(event_time, action, **kwargs):
+        """
+        Schedule event with threading
+
+        Params:
+        ==========
+        event_time      datetime format
+        action          function
+        **kwargs        function arguments
+        """
+        delta = (event_time - datetime.datetime.now()).total_seconds()
+        if delta > 0:
+            logging.debug("time interval to next action is {}".format(delta))
+            T = threading.Timer(int(delta), action, **kwargs)
+            T.start()
+        else:
+            logging.debug("event {} scheduled in the past!".format(str(event_time)))
+
+

+ 348 - 0
valeriovive/twitter_agent.py

@@ -0,0 +1,348 @@
+import tweepy
+from tweepy import OAuthHandler
+import tweepy.streaming
+from tweepy import StreamListener
+from pymongo import MongoClient
+import logging
+import random
+from copy import copy
+
+class MyStreamListener(tweepy.StreamListener):
+
+    def on_status(self, status):
+        print(status.text)
+
+    def on_error(self, status_code):
+        if status_code == 420:
+            #returning False in on_data disconnects the stream
+            return False
+
+class TwitterAgent():
+    """
+    Twitter_agent class, initiated with keys, is a Tweepy based Object
+    TwitterAgent get init with a dictionary
+
+    Attributes
+
+    name String name of the agent
+    cfg  Dict conf
+    api  Tweepy Object
+    userdb Pymando db
+    twettsdb Pymando db
+    """
+    def __init__(self,name,cfg):
+        ##cfg is a json with
+            #consumer_key
+            #consumer_set
+            #access_token
+            #secret_token
+        self.name=name
+        self.userdb=None
+        self.tweetsdb=None
+        self.cfg =cfg
+        self.api =None
+        self.db_instance()
+        self.ERROR=[]
+        self.listener = None
+        self.streamer = None
+
+        ### loggers
+        self.logger = logging.getLogger(name+": TwitterAgent")
+        self.logger.info('created Twitter Agent{} obj'.format(self.name))
+    """
+    Authenticate
+    """
+    @staticmethod
+    def authenticate(cfg):
+        auth=OAuthHandler(cfg["consumer_key"],cfg["consumer_set"])
+        auth.set_access_token(cfg["access_token"],cfg["secret_token"])
+        return tweepy.API(auth), auth
+
+    def connect(self):
+        self.api , auth= self.authenticate(self.cfg)
+        self.streamer = tweepy.Stream(auth, listener=MyStreamListener())
+
+    @property
+    def connected(self):
+        try:
+            return self.api.me()
+        except:
+            self.logger.error(ValueError)
+
+    """
+    Instanciate Pymong db [a dictionary type]
+    tweetsdb will cotain the whole tweet
+    userdb will contain tweets's authors and relative followers
+    """
+    def db_instance(self):
+        try:
+            client=MongoClient('localhost', 27017)
+            db=client.get_database('dict')
+            self.db=db[self.name]
+            #error list it's for those user resulting missing to followers retrieve
+        except:
+            raise ValueError("Error during mongodb initialization")
+
+    """
+    Add Friends to authenticated user profile
+
+    Parameters:
+    buddy_list list(strings) Users list for next session
+    hash_list  list(strings) Hash list for next session
+    """
+    def add_friends(self, buddy_list, hash_list):
+        self.logger.debug("add_friends")
+        if not isinstance(buddy_list,list):
+            buddy_list=list(buddy_list)
+        for buddy in buddy_list:
+            try:
+                self.api.create_friendship(user_id=buddy)
+            except:
+                logging.warning("{} didn't find this buddy: {} \n".format(self.name,buddy))
+
+    """
+    Search the hash_list and retweet some status
+
+    Parameters:
+    buddy_list list(strings) Users list for next session
+     hash_list  list(strings) Hash list for next session
+    """
+    def search_and_retweet(self, buddy_list, hash_list):
+        self.logger.debug("search_and_retweet")
+        if not isinstance(hash_list,list):
+            hash_list=list(hash_list)
+        for tag in hash_list:
+            if random.random() > 0.7:
+                hash_cursor = tweepy.Cursor(self.api.search, q="#"+tag).items()
+                for tweet in hash_cursor:
+                    if tweet.retweeted: continue
+                    if random.random() > 0.7:
+                        print(tweet.id, tweet.user, tweet.retweeted)
+                        self.api.retweet(tweet.id)
+        return 0
+            # cursor=tweepy.Cursor("c", id=user, count=5000).pages()
+
+    """
+    Search the hash_list and follow some users
+
+    Parameters:
+    buddy_list list(strings) Users list for next session
+    hash_list  list(strings) Hash list for next session
+    """
+
+    def search_and_follow(self, buddy_list, hash_list):
+        self.logger.debug("search_and_follow")
+        if not isinstance(hash_list,list):
+            hash_list=list(hash_list)
+        my_hash_list = copy(hash_list)
+        random.shuffle(my_hash_list)
+        my_hash_list = my_hash_list[:int(0.3*len(my_hash_list))]
+        for tag in my_hash_list:
+            self.logger.debug("searching for hashtag "+tag)
+            hash_cursor = tweepy.Cursor(self.api.search, q="#"+tag).items(5)
+            for num, tweet in enumerate(hash_cursor):
+                if random.random() > 0.8:
+                    self.logger.debug("searching for tweet "+tweet.text)
+                    self.api.create_friendship(tweet.author.id)
+        return 0
+
+    """
+    Search the buddy_list and retweet some users
+
+    Parameters:
+    buddy_list list(strings) Users list for next session
+    hash_list  list(strings) Hash list for next session
+    """
+    def retweet_my_friends(self, buddy_list, hash_list):
+        self.logger.debug("retweet_my_friends")
+        if not isinstance(buddy_list, list):
+            buddy_list=list(buddy_list)
+        random.shuffle(buddy_list)
+        for buddy in buddy_list:
+            try:
+                tweets = self.api.user_timeline(screen_name=buddy)
+                #self.stream.filter(buddy, _with='followings', async = True)
+            except:
+                logging.warning("user {} timeline not accesible \n".format(buddy))
+                for tweet in tweets:
+                    if random.random()>0.8:
+                        self.api.retweet(tweet.id)
+        return 0
+
+
+    def destroy_all_friends(self):
+        self.logger.debug("destroy_all_friends")
+        for friend in self.api.friends_ids(self.api.me().id):
+            self.api.destroy_friendship(friend)
+
+    #This function obtain tweet for the indicated query,
+    #it will save into db untill the element get the willed value-count.
+    #in order to start from last saved tweet after a possible break,
+    #it uses the external parameters lastid, wich is obtained from db itself in runtime
+
+    """
+    Save the user user timeline
+    """
+    def get_user_timeline(self):
+        self.logger.debug("get_timeline")
+        try:
+            timeline = self.api.home_timeline(count=200)
+        except:
+            self.logger.error("User timeline return error")
+        for tweet in timeline:
+            self.logger.debug("Tweet from {}, : {}".format(tweet.author.name,tweet.text))
+            self.db.insert({"status":{
+                                "author_name":tweet.author.name,
+                                "text": tweet.text,
+                                "status":tweet._json}
+                                })
+            self.logger.debug("item inserted in the db")
+        return 0
+#     def save_tweets(self,db,query,api=None,count=5000,lastid=0):
+        # api=self.api
+        # try:
+            # while db.count() <count:
+                # cursor=api[0].search(q=query,since_id=lastid)
+                # for tweet in cursor:
+    # #some information will be saved, this isn't complete but exahustive
+                    # db.insert({"status":{"author_name":tweet.author.name,\
+                                # "author_id":tweet.author.id,\
+                                # "author_json":tweet.author._json,\
+                                # "status_json":tweet._json}\
+                                # })
+                    # lastid=tweet.id
+            # return lastid
+        # except:
+            # return lastid
+
+    #this function returns all elements already "scrapied", that is which followers already are in userdb.
+    #this is to restart program since any lose too.
+    # def scrapied (self,userdb=None):
+        # userdb=self.userdb
+        # for i in userdb.find():
+            # yield int(i['user'].keys()[0])
+
+    # #a simple rotate function very usefull for api index scrolling
+    # def rotate(self,l):
+        # return l[1:] + l[:1]
+
+    # #it parses tweetsdb and return all authors, obviously the db is parsed only at first instance,
+    # #then everything is saved to user_list, and authors popped from there.
+    # #
+
+    # def get_users(self, tweetsdb, last_user=0, user_list=False):
+        # tweetsdb=self.tweetsdb
+        # if user_list:
+    # #pop an item from list and return it
+            # user_list.pop(0)
+            # return user_list
+        # else:
+            # users=[int(str(user['status']['author_id']).strip()) for user in tweetsdb.find()]
+            # user_list=sorted(set(users),reverse=True)[last_user:]
+    # #don't reapeat user
+            # for user in scrapied(userdb):
+                # try:
+                    # user_list.remove(user)
+                # except:
+                    # continue
+            # return user_list
+
+    # #most difficult to write down!
+    # #this function return followers for each author, adopting some tricks to keep memory of cursor
+    # #and same time get a new api when apiratelimit is exceeded
+    # # def get_followers(self,user,api=none):
+        # # api=self.api
+        # # followers=[]
+        # # count=1
+        # # cursor=tweepy.cursor(api[0].followers_ids, id=user, count=5000).pages()
+        # # while true:
+            # # try:
+                # # for page in cursor:
+                    # # followers.extend(page)
+                    # # print "page", count, "of user", user
+                    # # sys.stdout.flush()
+                    # # count +=1
+                # # return followers
+
+            # # except tweepy.ratelimiterror:
+    # #new api in case is at zero page retrieved
+                # # if cursor.next_cursor==-1:
+                    # # self.rotate(self.api)
+                    # # self.get_followers(user)
+                # # else:
+                    # # print "let's take a break, it will restart                        from last page; api_index is", api[0],"current cursor", cursor.next_cursor
+                    # # sys.stdout.flush()
+                    # # for i in range(15):
+                        # # print 15-i, "minutes to wait"
+                        # # time.sleep(60)
+                    # # continue
+            # # except:
+                # # print "Unexpected!!! on user", user
+                # # self.ERROR.append(user)
+                # # break
+
+    # #this function is a kind of main, retrieve users and scrapies followers for each one, then pop user and reapeat.
+    # def followers(self,api=None,userdb=None,tweetsdb=None):
+        # api=self.api
+        # tweetsdb=self.tweetsdb
+        # userdb=self.userdb
+        # user_list=get_users(tweetsdb)
+        # while user_list:
+            # if api[0].rate_limit_status()['resources']['followers']['/followers/ids']['remaining'] <1:
+                # api=self.rotate(api)
+                # print ("api_index has incremented")
+
+            # user=user_list[0]
+            # followers =self.get_followers(user,api=api)
+            # userdb.insert({"user":{str(user):followers}})
+            # user_list=get_users(tweetsdb,user_list=user_list)
+
+
+
+
+# # In[26]:
+
+# #lastid=int(tweetsdb.find()[len([tweetsdb.find()])-1]['status']['status_json']['id_str'])
+
+
+# # In[33]:
+
+# #len(list(scrapied(userdb)))
+
+
+# # In[35]:
+
+# #len(get_users(tweetsdb))
+
+
+# # In[ ]:
+# '''
+# lastid=int(tweetsdb.find()[len([tweetsdb.find()])-1]['status']['status_json']['id_str'])
+# count=10000
+# #keep it running until count
+# while tweetsdb.count() < count:
+    # api_index=0
+    # lastid=get_tweets(db=tweetsdb,api=api,query="Daesh",count=count,lastid=lastid,api_index=api_index)
+    # rotate(api)
+    # print tweetsdb.count()
+    # time.sleep(60*15)
+
+# if len(get_users(tweetsdb)):
+    # followers(api=api,userdb=userdb,tweetsdb=tweetsdb)
+   # '''
+
+
+# # In[9]:
+
+
+
+
+# # In[8]:
+
+
+
+
+# # In[34]:
+
+
+# # In[84]: