Spaces:
Runtime error
Runtime error
#!/usr/bin/env python | |
# coding: utf-8 | |
import json | |
import os | |
import re | |
import time | |
from random import random | |
import socket | |
from threading import Thread | |
from time import sleep | |
test_html = ''' | |
<!-- Header --> | |
<header class="w3-display-container w3-content w3-wide" style="max-width:1500px;" id="home"> | |
<img class="w3-image" src="https://cdn.pixabay.com/photo/2018/12/10/16/22/city-3867295_960_720.png" alt="Architecture" width="1500" height="800"> | |
<div class="w3-display-middle w3-margin-top w3-center"> | |
<h1 class="w3-xxlarge w3-text-white"><span class="w3-padding w3-black w3-opacity-min"><b>WATCH</b></span> <span class="w3-hide-small w3-text-dark-grey">Tower</span></h1> | |
</div> | |
</header> | |
<!-- Container (About Section) --> | |
<div class="w3-content w3-container w3-padding-64" id="about"> | |
<h3 class="w3-center">Block Violent Content Before It Reaches Your Feed</h3> | |
<p class="w3-center"><em>WatchTower identifies, blocks, and filters out violent and radical content before it reaches your Twitter feed. | |
</em></p> | |
<br> | |
<p>WatchTower works to protect you from violent, misinformation, hate speech and other malicious communication by using a suite of machine learning models to identify user accounts that post content that commonly falls into these categories. WatchTower is broken down into two components, the first utilises the Twitter streaming API and applies a suite of machine learning models to identify users that commonly post malicious information, while the second element provides a web UI where users can authenticaate with Twitter and tailor the types and thresholds for the accounts they block. </p> | |
<br> | |
<p> WatchTower was developed solely by James Stevenson and primarily uses Pinpoint, a machine learning model also developed by James. The future roadmap sees WatchTower incoperate other models for identifying contrent such as misinformation and hate speech. More on Pinpoint and the model WatchTower uses to identify violent extremism can be seen below.</p> | |
<p class="w3-large w3-center w3-padding-16">Model Accuracy:</p> | |
<p class="w3-center"><em>Machine learning models can be validated based on several statistics. These statistics for Pinpoint the main ML model used by WatchTower can be seen below. </p> | |
<br> | |
<p class="w3-wide"><i class="fa fa-camera"></i>Accuracy</p> | |
<div class="w3-light-grey"> | |
<div class="w3-container w3-padding-small w3-dark-grey w3-center" style="width:73%">73%</div> | |
</div> | |
<p class="w3-wide"><i class="fa fa-laptop"></i>Recall</p> | |
<div class="w3-light-grey"> | |
<div class="w3-container w3-padding-small w3-dark-grey w3-center" style="width:62%">62%</div> | |
</div> | |
<p class="w3-wide"><i class="fa fa-photo"></i>Precision</p> | |
<div class="w3-light-grey"> | |
<div class="w3-container w3-padding-small w3-dark-grey w3-center" style="width:78%">78%</div> | |
</div> | |
<p class="w3-wide"><i class="fa fa-photo"></i>F-Measure</p> | |
<div class="w3-light-grey"> | |
<div class="w3-container w3-padding-small w3-dark-grey w3-center" style="width:69%">69%</div> | |
</div> | |
</div> | |
<div class="w3-row w3-center w3-dark-grey w3-padding-16"> | |
<div class="w3-quarter w3-section"> | |
<span class="w3-xlarge">14+</span><br> | |
Partners | |
</div> | |
<div class="w3-quarter w3-section"> | |
<span class="w3-xlarge">55+</span><br> | |
Projects Done | |
</div> | |
<div class="w3-quarter w3-section"> | |
<span class="w3-xlarge">89+</span><br> | |
Happy Clients | |
</div> | |
<div class="w3-quarter w3-section"> | |
<span class="w3-xlarge">150+</span><br> | |
Meetings | |
</div> | |
</div> | |
<br> | |
<!-- Container (Portfolio Section) --> | |
<div class="w3-content w3-container w3-padding-64" id="portfolio"> | |
<h3 class="w3-center">Chirp Development Challenge 2022</h3> | |
<p class="w3-center"><em>WatchTower was developed for the Chirp 2022 Twitter API Developer Challenge</em></p> | |
</div><p> Watchtower was developed solely by James Stevenson for the Chirp 2022 Twitter API Developer Challenge. More infomration of this can be found below.</p> | |
<br> | |
<img class="w3-image" src="https://cdn.cms-twdigitalassets.com/content/dam/developer-twitter/redesign-2021-images/blog2022/chirp/Chirp-Hero-Banner.jpg.twimg.1920.jpg" alt="Architecture" width="1500" height="800"> | |
<br> | |
<!-- Modal for full size images on click--> | |
<div id="modal01" class="w3-modal w3-black" onclick="this.style.display='none'"> | |
<span class="w3-button w3-large w3-black w3-display-topright" title="Close Modal Image"><i class="fa fa-remove"></i></span> | |
<div class="w3-modal-content w3-animate-zoom w3-center w3-transparent w3-padding-64"> | |
<img id="img01" class="w3-image"> | |
<p id="caption" class="w3-opacity w3-large"></p> | |
</div> | |
</div> | |
<script> | |
// Modal Image Gallery | |
function onClick(element) { | |
document.getElementById("img01").src = element.src; | |
document.getElementById("modal01").style.display = "block"; | |
var captionText = document.getElementById("caption"); | |
captionText.innerHTML = element.alt; | |
} | |
// Change style of navbar on scroll | |
window.onscroll = function() {myFunction()}; | |
function myFunction() { | |
var navbar = document.getElementById("myNavbar"); | |
if (document.body.scrollTop > 100 || document.documentElement.scrollTop > 100) { | |
navbar.className = "w3-bar" + " w3-card" + " w3-animate-top" + " w3-white"; | |
} else { | |
navbar.className = navbar.className.replace(" w3-card w3-animate-top w3-white", ""); | |
} | |
} | |
// Used to toggle the menu on small screens when clicking on the menu button | |
function toggleFunction() { | |
var x = document.getElementById("navDemo"); | |
if (x.className.indexOf("w3-show") == -1) { | |
x.className += " w3-show"; | |
} else { | |
x.className = x.className.replace(" w3-show", ""); | |
} | |
} | |
</script> | |
</body> | |
</html> | |
''' | |
import gradio as gr | |
import tweepy | |
from fastapi import FastAPI, Request | |
consumer_token = os.getenv('CONSUMER_TOKEN') | |
consumer_secret = os.getenv('CONSUMER_SECRET') | |
my_access_token = os.getenv('ACCESS_TOKEN') | |
my_access_secret = os.getenv('ACCESS_SECRET') | |
global_oauth1_user_handler = None | |
bearer = os.getenv('BEARER') | |
oauth1_user_handler = tweepy.OAuth1UserHandler( | |
consumer_token, consumer_secret, | |
callback="http://127.0.0.1:7860/" | |
) | |
target_website = oauth1_user_handler.get_authorization_url(signin_with_twitter=True) | |
block = gr.Blocks(css=".container { max-width: 800px; margin: auto; }") | |
chat_history = [] | |
def get_client_from_tokens(oauth_verifier, oauth_token): | |
new_oauth1_user_handler = tweepy.OAuth1UserHandler( | |
consumer_token, consumer_secret, | |
callback="http://127.0.0.1:7860/" | |
) | |
new_oauth1_user_handler.request_token = { | |
"oauth_token": oauth_token, | |
"oauth_token_secret": consumer_secret | |
} | |
access_token, access_token_secret = new_oauth1_user_handler.get_access_token( | |
oauth_verifier | |
) | |
their_client = tweepy.Client( | |
bearer_token=bearer, | |
consumer_key=consumer_token, | |
consumer_secret=consumer_secret, | |
access_token=access_token, | |
access_token_secret=access_token_secret | |
) | |
return their_client | |
def get_oath_headers(): | |
oauth_verifier = None | |
oauth_token = None | |
did_find = False | |
if hasattr(block, "server"): | |
for connection in block.server.server_state.connections: | |
# connection_app_id = connection.app.app.blocks.app_id | |
# if active_app_id == connection_app_id: | |
# print("Its a match") | |
if connection.headers != None: | |
for header in connection.headers: | |
header = header[1].decode() | |
if "oauth_verifier" in header: | |
oauth_verifier = re.search(r"oauth_verifier=(.+)", header).group(1) | |
oauth_token = re.search(r"oauth_token=(.+)&", header).group(1) | |
if oauth_token and oauth_verifier: | |
did_find = True | |
break | |
if did_find: | |
break | |
return oauth_verifier, oauth_token | |
def block_users(client, threshold, dataset): | |
num_users_blocked = 0 | |
for filename in os.listdir("users"): | |
filename = os.path.join("users", filename) | |
user_file = open(filename, "r") | |
users = json.load(user_file) | |
for user in users: | |
if threshold >= user["threshold"]: | |
user = user["username"].strip() | |
user_id = client.get_user(username=user) | |
finished = False | |
while not finished: | |
try: | |
client.block(target_user_id=user_id.data.id) | |
except tweepy.errors.TooManyRequests as e: | |
print(e) | |
time.sleep(240) | |
continue | |
finished = True | |
me = client.get_me() | |
print("{} blocked {}".format(me.data["username"], user)) | |
num_users_blocked = num_users_blocked + 1 | |
return num_users_blocked | |
def has_oath_header(): | |
headers = get_oath_headers() | |
if headers[0] == None: | |
return False | |
else: | |
return True | |
username_populated = False | |
def chat(radio_score = None, selected_option = None): | |
global client | |
history = [] | |
# app id | |
if radio_score != None and selected_option != None: | |
response = "no blocking" | |
if client != None: | |
chat_history.append(["Model tuned to a '{}%' threshold and is using the '{}' dataset.".format(radio_score, selected_option), | |
"{} Account blocking initialised".format(selected_option.capitalize())]) | |
num_users_blocked = block_users(client,radio_score,selected_option) | |
chat_history.append(["Blocked {} user account(s).".format(num_users_blocked), "Thank you for using Watchtower."]) | |
elif radio_score != None or selected_option != None: | |
chat_history.append(["Initialisation error!","Please tune the model by using the above options"]) | |
return chat_history | |
def infer(prompt): | |
pass | |
have_initialised = False | |
client = None | |
name = None | |
def changed_tab(): | |
global have_initialised | |
global chatbot | |
global chat_history | |
global client | |
global name | |
name = "no username" | |
chat_history = [["Welcome to Watchtower.".format(name), "Log in via Twitter and configure your blocking options above."]] | |
if client != None and name != "no username": | |
chat_history = [["Welcome {}".format(name), "Initialising WatchTower"]] | |
print("changed tabs - {}".format(name)) | |
chatbot.value = chat_history | |
chatbot.update(value=chat_history) | |
elif has_oath_header() and client==None: | |
tokens = get_oath_headers() | |
if tokens[0] and client==None: | |
client = get_client_from_tokens(tokens[0],tokens[1]) | |
name = client.get_me().data.name | |
have_initialised = True | |
chat_history = [["Welcome {}".format(name), "Initialising WatchTower"]] | |
chatbot.value = chat_history | |
chatbot.update(value=chat_history) | |
elif not has_oath_header() and not have_initialised: | |
chatbot.value = chat_history | |
chatbot.update(value=chat_history) | |
with block: | |
gr.HTML(''' | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css"> | |
<!-- Navbar (sit on top) --> | |
<div class="w3-top"> | |
<div class="w3-bar w3-white w3-wide w3-padding w3-card"> | |
<p class="w3-bar-item w3-button"><b>WATCH</b> Tower</p> | |
</div> | |
</div> | |
''') | |
gr.HTML("<center><p><br></p></center>") | |
#todo check if user signed in | |
user_message = "Log in via Twitter and configure your blocking options above." | |
chat_history.append(["Welcome to Watchtower.",user_message]) | |
tabs = gr.Tabs() | |
with tabs: | |
intro_tab = gr.TabItem("Introduction") | |
with intro_tab: | |
gr.HTML(test_html) | |
prediction_tab = gr.TabItem("Getting Started") | |
with prediction_tab: | |
gr.HTML(''' | |
<header class="w3-display-container w3-content w3-wide" style="max-height:250px;" id="home"> | |
<img class="w3-image" src="https://cdn.pixabay.com/photo/2018/12/10/16/22/city-3867295_960_720.png" alt="Architecture" width="1500" height="800"> | |
<div class="w3-display-middle w3-margin-top w3-center"> | |
<h1 class="w3-xxlarge w3-text-white"><span class="w3-padding w3-black w3-opacity-min"><b>WATCH</b></span> <span class="w3-hide-small w3-text-dark-grey">Tower</span></h1> | |
</div> | |
</header> | |
''') | |
with gr.Group(): | |
with gr.Box(): | |
with gr.Row().style(mobile_collapse=False, equal_height=True): | |
gr.HTML( | |
value='<a href={}><img src="https://cdn.cms-twdigitalassets.com/content/dam/developer-twitter/auth-docs/sign-in-with-twitter-gray.png.twimg.1920.png" alt="Log In With Twitter"></a><br>'.format( | |
target_website)) | |
with gr.Row().style(mobile_collapse=False, equal_height=True): | |
radio = gr.CheckboxGroup(value="Violent", choices=["Violent", "Hate Speech", "Misinformation"], | |
interactive=False, label="Behaviour To Block") | |
slider = gr.Slider(value=80, label="Threshold Certainty Tolerance") | |
chatbot = gr.Chatbot(value=chat_history, label="Watchtower Output").style() | |
btn = gr.Button("Run WatchTower").style(full_width=True) | |
#radio.change(fn=chat, inputs=[radio], outputs=chatbot) | |
#slider.change(fn=chat, inputs=[slider], outputs=chatbot) | |
#text.submit(fn=chat, inputs=[text,text], outputs=chatbot) | |
btn.click(fn=chat, inputs=[slider,radio], outputs=chatbot) | |
tabs.change(fn=changed_tab, inputs=None, outputs=None) | |
gr.Markdown( | |
"""___ | |
<p style='text-align: center'> | |
Created by <a href="https://twitter.com/borisdayma" target="_blank">Boris Dayma</a> et al. 2021-2022 | |
<br/> | |
<a href="https://github.com/borisdayma/dalle-mini" target="_blank">GitHub</a> | <a href="https://wandb.ai/dalle-mini/dalle-mini/reports/DALL-E-mini-Generate-images-from-any-text-prompt--VmlldzoyMDE4NDAy" target="_blank">Project Report</a> | |
</p>""" | |
) | |
block.launch(enable_queue=False) |