import os import requests from otree.api import Currency as c, currency_range from ._builtin import Page, WaitPage from .models import Constants import numpy as np import json from NewsSocialSignaling import TwitterProcessor, TwitterAPI import pickle import io import matplotlib matplotlib.use('Agg') from matplotlib import pyplot as plt import base64 import copy import datetime as dt import threading import time from google.cloud import storage import hashlib print(os.environ["GOOGLE_APPLICATION_CREDENTIALS"]) storage_client = storage.Client() bucket = storage_client.bucket('newsconsumption') def upload_blob(source_file_name, destination_blob_name): """Uploads a file to the bucket.""" # bucket_name = "your-bucket-name" # source_file_name = "local/path/to/file" # destination_blob_name = "storage-object-name" blob = bucket.blob(destination_blob_name) blob.upload_from_filename(source_file_name) def infographic_to_graphic(fig, sn, suffix): buffer = io.BytesIO() fig.savefig(buffer, format='png', dpi=300) static_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), '_static') fn = os.path.join(static_path, 'infographics', sn + suffix + '.png') if not os.path.exists(os.path.dirname(fn)): os.makedirs(os.path.dirname(fn)) fig.savefig(fn, format='png', dpi=300) buffer.seek(0) image_png = buffer.getvalue() buffer.close() # unique string fn = os.path.join(static_path, 'infographics', sn + suffix + '.png') # now upload to google bucket upload_blob(source_file_name=fn, destination_blob_name=os.path.basename(fn)) # upload static site and return url hsn = hashlib.md5((sn + suffix).encode()).hexdigest() fn = os.path.join(static_path, 'infographics', hsn + '.html') with open(os.path.join(static_path, 'infographic.html'), 'r') as f: html = f.read() remote_fn = "https://storage.googleapis.com/newsconsumption/{0}.png".format(sn) html = html.replace('', ''.format(remote_fn)) html = html.replace( '', ''.format( "https://storage.googleapis.com/newsconsumption/{0}".format(sn + suffix + '.png') )) with open(fn, 'w') as f: f.write(html) upload_blob(source_file_name=fn, destination_blob_name=os.path.basename(fn)) graphic_bytes = base64.b64encode(image_png) graphic = graphic_bytes.decode('utf-8') graphic_link = "https://storage.googleapis.com/newsconsumption/{0}".format(os.path.basename(fn)) return graphic, image_png, graphic_link class SummaryStatistic(Page): form_model = 'player' live_method = 'live_handler' def vars(self): plt.close('all') public_treatment = self.participant.vars['public_treatment'] placebo_treatment = self.participant.vars['placebo_treatment'] if 'shown_summary_stat' in self.participant.vars and self.participant.vars['shown_summary_stat']: name = 'post_revisions' suffix = '_' + name user_name = 'user_data' + suffix if user_name not in self.participant.vars or (dt.datetime.utcnow() - self.participant.vars['user_added' + suffix]).total_seconds() / 60 > 5: handle = self.participant.vars['twitter_handle'] try: user = TwitterAPI.get_user(screen_name=handle, get_friends=True, resample=True, max_pages_network=2) except Exception as e: self.participant.vars['errors'] = str(e) raise e self.participant.vars['user_data' + suffix] = user self.participant.vars['user_added_' + name] = dt.datetime.utcnow() user = self.participant.vars['user_data' + suffix] retweet_page = True else: print('Vars Baseline') suffix = '_baseline' retweet_page = False user = self.participant.vars['user_data_baseline'] print('Accounts following: {0}'.format(TwitterProcessor.accounts_following(user=user))) info = TwitterProcessor.build_infographic(user=user, savefig=False) fig = info['fig'] self.participant.vars['user' + suffix] = user self.participant.vars['img_pickled' + suffix] = pickle.dumps(fig) graphic, graphic_bytes, graphic_fn = infographic_to_graphic(fig=fig, sn=user['screen_name'], suffix='') self.participant.vars['infographic_link'] = graphic_fn print(graphic_fn) # format tweet_text for url tweet_text_public = info['text'] tweet_text_public = tweet_text_public.replace('%', '%25').replace('@', '%40') tweet_text_public += '%0A%0AView your news diet at https://newsconsumption.mit.edu/room/Start\n' tweet_text_public += ' ' + self.participant.vars['infographic_link'] if 'infographic_link' in self.participant.vars else '' tweet_text_private = 'View your news diet at https://newsconsumption.mit.edu/room/Start' if public_treatment: tweet_text = tweet_text_public else: tweet_text = tweet_text_private # get summary of friends information (if in network treatment) peer_info = self.player.add_peer_info(user) self.participant.vars['eligible_for_peer'] = False peer_treatment = False peer_graphic = None if isinstance(peer_info, dict) and len(peer_info['sampled_friends']) > 0: self.participant.vars['eligible_for_peer'] = True peer_treatment = self.participant.vars['peer_treatment'] # only update this to true if eligible info_peer = TwitterProcessor.build_infographic_peers(user=user, peer_data=peer_info, savefig=False) peer_graphic, peer_graphic_bytes, peer_graphic_link = infographic_to_graphic(fig=info_peer['fig'], sn=user['screen_name'], suffix='_peers') else: if isinstance(self.player.log, type(None)): self.player.log = '' self.player.log += ';' + json.dumps({ 'log_type': 'ineligible_peer_treatment', 'public_treatment': self.participant.vars['public_treatment'], 'peer_treatment': peer_treatment, 'peer_info': peer_info }) return { 'infographic': graphic, 'retweet_page': retweet_page, 'public_treatment': public_treatment, 'placebo_treatment': placebo_treatment, 'infographic_path': '/static/infographics/{0}.png'.format(user['screen_name']), 'tweet_text': tweet_text, 'tweet_text_public': tweet_text_public, 'tweet_text_private': tweet_text_private, 'peer_treatment': peer_treatment, 'peer_infographic': peer_graphic } def vars_for_template(self): vs = self.vars() self.player.live_handler(data={'vars_for_template': dict((el, vs[el]) for el in vs if 'infographic' not in el)}) return vs # def js_vars(self): # return self.vars() def before_next_page(self): self.participant.vars['shown_summary_stat'] = True class BonusLottery(Page): form_model = 'player' live_method = 'live_handler' def vars_for_template(self): return { 'public_treatment': self.participant.vars['public_treatment'], 'placebo_treatment': self.participant.vars['placebo_treatment'], 'bonus_lottery_amount': self.participant.vars['bonus_lottery_amount'], } class Recommendations(Page): form_model = 'player' live_method = 'live_handler' def vars(self): n = 3 if 'recommendations' in self.participant.vars and len(self.participant.vars['recommendations']) > n: recs = self.participant.vars['recommendations'] else: user = self.participant.vars['user_baseline'] # determine which type of reccomedation to use recs_balanced = self.participant.vars['recommendations_balanced'] rec_type = self.participant.vars['recommendations_type'] recs_dict = TwitterProcessor.get_recommendations(user=user, recommendation_type=rec_type, num_recs=n*2, balanced=recs_balanced) recs = recs_dict['recs'] self.participant.vars['possible_possible_recommendations'] = copy.copy(recs_dict['possible_recs']) self.participant.vars['recommendations'] = copy.copy(recs_dict['recs']) return { 'recommendations': recs, 'rec_type': self.participant.vars['recommendations_type'], 'balanced': self.participant.vars['recommendations_balanced'], 'public_treatment': self.participant.vars['public_treatment'], 'recommendations_page_reminder': self.participant.vars['recommendations_page_reminder'] } def vars_for_template(self): return self.vars() def js_vars(self): return self.vars() class Endline(Page): form_model = 'player' live_method = 'live_handler' form_fields = [ 'debrief_ideology', 'debrief_ideologyTwitterFollowers', 'debrief_ideologyTwitterFollow', 'debrief_ideologyNews', 'debrief_ideologyTwitterFollowersNews', 'debrief_ideologyTwitterFollowNews', 'guess_lottery1', 'guess_lottery2' ] class Feedback(Page): form_model = 'player' live_method = 'live_handler' form_fields = [ 'email', 'debrief_instructions', 'debrief_summary_stat', 'debrief_technical_glitches', 'debrief_why_publisher_slant', 'debrief_why_publisher_popularity', 'debrief_why_publisher_truthsworthy', 'debrief_why_publisher_ideology', 'debrief_why_publisher_ideology_friends', 'debrief_why_publisher_ideology_followers', 'debrief_why_publisher_ideology_followees', 'debrief_why_publisher_own_close', 'debrief_why_publisher_own_far', 'debrief_why_publisher_peers_close', 'debrief_why_publisher_peers_far', 'debrief_why_publisher_any_other', 'debrief_why_publisher', 'debrief_tweet_scale', 'debrief_tweet_question', 'debrief_tweet_why', 'debrief_retweet_scale', 'debrief_retweet_scale_selected' ] class ThankYou(Page): form_model = 'player' page_sequence = [SummaryStatistic, BonusLottery, Recommendations, SummaryStatistic, Endline, Feedback, ThankYou]