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 is_displayed(self):
k = 'show_summary_statistic'
return self.participant.vars[k]
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, wait_on_rate_limit=False)
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
if public_treatment:
tweet_text = info['text']
tweet_text = tweet_text.replace('%', '%25').replace('@', '%40')
tweet_text += '%0A%0AView your news diet at https://bit.ly/3Fx2GxV\n'
tweet_text += ' ' + self.participant.vars['infographic_link'] if 'infographic_link' in self.participant.vars else ''
else:
tweet_text = 'View your news diet at https://bit.ly/3Fx2GxV'
# 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,
'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']
}
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_data_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 PublisherPage(Page):
form_model = 'player'
live_method = 'live_handler'
def vars(self):
return {
'selected_publisher': self.participant.vars['selected_publisher'],
'public_treatment': self.participant.vars['public_treatment'],
'placebo_treatment': self.participant.vars['placebo_treatment']
}
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_instructions', 'debrief_summary_stat', 'debrief_technical_glitches',
'debrief_why_publisher_slant', 'debrief_why_publisher_popularity', 'debrief_why_publisher_truthsworthy',
'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']
def vars(self):
return {
'selected_publisher': self.participant.vars['selected_publisher'],
'public_treatment': self.participant.vars['public_treatment'],
'placebo_treatment': self.participant.vars['placebo_treatment']
}
def vars_for_template(self):
return self.vars()
def js_vars(self):
return self.vars()
class ThankYou(Page):
form_model = 'player'
page_sequence = [SummaryStatistic, BonusLottery, Recommendations, PublisherPage, Endline, ThankYou]
# page_sequence = [Endline,]