Skip to content

Instantly share code, notes, and snippets.

@SteelCrow
Last active November 28, 2023 15:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SteelCrow/963ef64ebf5a9b0081c7805f6e5dabe0 to your computer and use it in GitHub Desktop.
Save SteelCrow/963ef64ebf5a9b0081c7805f6e5dabe0 to your computer and use it in GitHub Desktop.
Anti-Quishing
from qreader import QReader
import gradio as gr
# Pandas helps us with data transformation into DataFrame
# for further use in BarPlot UI widget
import pandas as pd
import vt
# Main class of our recogniser and segmentator
qreader = QReader()
# Our workhorse function
async def detect_and_decode_qr_code(vt_key, img):
# Array of invisible BarPlots if something goes wrong
analysis = [
gr.BarPlot(visible=False),
gr.BarPlot(visible=False),
gr.BarPlot(visible=False),
gr.BarPlot(visible=False),
]
try:
decoded = qreader.detect_and_decode(img)
# We handle only one QR code in the picture
# that's why we check result for type
if decoded is not None and type(decoded) is tuple:
# Prepare the VirusTotal client class
async with vt.Client(vt_key) as client:
# Iterate through all potential links in
# the QR coode
for idx in range(len(decoded)):
# Because we have only 4 pre-defined
# widgets
if idx > 4:
break
# Ask VirusTotal about the URL
res = await client.scan_url_async(
decoded[idx], wait_for_completion=True
)
# Transform the verdict from VT to a
# pandas DataFrame because we have no other
# option to provide it to the BarPlot widget
df = pd.DataFrame(
res.stats.items(),
columns=["categories", "values"]
)
# Create BarPlot
anylisis[idx] = gr.BarPlot(
df,
x="categories",
y="values",
color="categories",
vertical=False,
visible=True,
scale=2,
width=600,
height=500,
)
return analysis
except Exception as e:
# Awful error handling, but it's sufficient for PoC
print(e)
# Always return an array of invisible BarPlot widgets
# in case of errors
return analysis
# Clear the state of widgets
def reset_state(img, i0, i1, i2, i3):
return (
gr.update(value=None),
gr.update(value=""),
gr.update(value=""),
gr.update(value=""),
gr.update(value=""),
)
# Gradio interface description
with gr.Blocks() as app:
with gr.Row():
with gr.Column():
# Sensitive info! We create textbox input
# only for quick prototyping; always
# use secret management
# solution in production
vt_key = gr.Textbox(label="Virus Total Key", type="password")
img_in = gr.Image()
reset = gr.Button("Reset")
# Ugly hack for multi-link case in QR code,
# Gradio does not support dynamic widgets
# so we have to allocate them beforehand
with gr.Column():
output0 = gr.BarPlot(visible=False)
output1 = gr.BarPlot(visible=False)
output2 = gr.BarPlot(visible=False)
output3 = gr.BarPlot(visible=False)
# Make interface alive; when you drop or select
# an image for analysis it will automatically run our
# function and return results
img_in.change(
detect_and_decode_qr_code,
[vt_key, img_in],
[output0, output1, output2, output3],
)
# To eliminate some pesky bugs in interface,
# clear the state of widgets
reset.click(
reset_state,
[img_in, output0, output1, output2, output3],
[img_in, output0, output1, output2, output3],
)
app.launch()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment