Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save qubodup/50b839b236076b5db5c25613350ce356 to your computer and use it in GitHub Desktop.
Save qubodup/50b839b236076b5db5c25613350ce356 to your computer and use it in GitHub Desktop.
Sound Attribution Tool: Freesound Super Credits see https://freesound.org/forum/legal-help-and-attribution-questions/34552/
# The code is dedicated to the public domain https://creativecommons.org/publicdomain/mark/1.0/
# A very simple Flask Hello World app for you to get started with...
# SECURITY RISK START
FSKEY = "FREESOUND API KEY"
# SECURITY RISK OVER
html_header = """<!DOCTYPE HTML>
<html>
<head>
<title>Freesound Super Credits HTML &amp; text author attribution &amp; license generator</title>
<style>
#slim { margin: 0 auto; width: 800px; }
textarea { height: 200px; width: 100%%; }
.error { background-color: orangered; color: black; }
.warning { background-color: gold; color: black; }
</style>
</head>
<body>
"""
html_footer = """
</body>
</html>
"""
# Creates license strings NEEDS TO BE UPDATED NOW THAT CCBY4.0 IS AVAILABLE?
def getLicenseName(url):
name = "Unknown License"
if url == "http://creativecommons.org/licenses/by/3.0/":
name = "CC-BY 3.0"
elif url == "http://creativecommons.org/publicdomain/zero/1.0/":
name = "CC0"
elif url == "http://creativecommons.org/licenses/by-nc/3.0/":
name = "CC-BY-NC 3.0"
elif url == "http://creativecommons.org/licenses/sampling+/1.0/":
name = "CC-Sampling+"
return name
# Remove "www." from links
def getShortLink(url):
return url.replace("http://www.", "http://")
#from flask import Flask
from flask import Flask, request, url_for
import urllib.request
import json
import html
app = Flask(__name__)
app.secret_key = 'IDONTKNOWWHATTHISIS'
@app.route('/')
def hello_person():
html_content = """
<div id="slim">
<h1>Freesound Super Credits</h1>
<p>Freesound credits generator which formats author attribution and license information for HTML (webistes, blogs) &amp; plaintext (YouTube descriptions and readme files).</p>
<p>If this tool is inconvenient, please write how you would prefer it to qubodup@gmail.com, it might take just a minute to make using this site comfortable for you.</p>
<h2>Form</h2>
<p>Please insert a newline-divided list of Freesound sound IDs (11), URLs (http://freesound.org/people/Bram/sounds/11/) or filenames (11__bram__sweep-log.wav):</p>
<p class="warning">Warning: you might want to edit your input if there are errors but your browser might forget the data, so save it in a text file using gedit (Linux), TextEdit (OS X) or notepad.exe (Windows).</p>
<form method="POST" action="%s"><textarea name="ids"></textarea><input type="submit" value="Submit" /></form>
<h2>Sample data set</h2>
<p>You can use this text to test both attribution generation as well as error handling:</p>
<pre>http://www.freesound.org/people/Woodylein/sounds/149818/
http://www.freesound.org/people/rjonesxlr8/sounds/213783/
http://www.freesound.org/people/Dpoggioli/sounds/213608/
http://www.freesound.org/people/Ears68/sounds/185150/
http://www.freesound.org/people/Woodylein/sounds/149817/
http://www.freesound.org/people/BROKENTEST/sounds/1zz1/
11__bram__sweep-log.wav
http://www.freesound.org/people/jediduke/sounds/126518/
http://www.freesound.org/people/Philip%%20Goddard/sounds/172163/
211985
http://www.freesound.org/people/qubodup/sounds/211985/
http://www.freesound.org/people/qubodup/sounds/211983/""" % (url_for('credits'))
html_content = html_content + html.escape("""
&asd&asd&amp;
<br>
<p style="background-color: red;">hm</p>""") + "</pre></div>"
return html_header + html_content + html_footer
@app.route('/credits', methods=['POST'])
def credits():
content = html.escape(request.form["ids"]).split("\n")
sounds = []
sounds_failed = []
sounds_duplicate = []
for i in content:
tmp = i.split("\n")[0].strip() # from text file input times, leaving just in case
#tmp = i
tmp2 = tmp.split("__")[0]
tmp3 = tmp.split("/sounds/")
if len(tmp3) > 1:
tmp_final = tmp3[1].split("/")[0]
else:
tmp_final = tmp2
# check if result is a duplicate
duplicate = False
for sound in sounds:
if sound[1] == tmp_final:
duplicate = True
# keep track of duplicates
sounds_duplicate.append("(\"" + i + "\" : \"" + tmp_final + "\")")
# add item to sounds table if it's not a dupliacte
if not duplicate:
# include original item for error feedback
sounds.append([i, tmp_final])
database = []
allUserNames = set()
allLicenseNames = set()
for sound in sounds:
url="http://freesound.org/apiv2/sounds/" + sound[1] + "/?fields=name,url,username,license&format=json" + "&token=" + FSKEY
try:
freesoundResponse = urllib.request.urlopen(urllib.request.Request(url))#, headers={'User-Agent': 'Mozilla/5.0'})) # I tried user agent because I first got 403 but it was actually a restriction by pythonanywhere. might not be needed but I'm afraid to break the request for now
except Exception as e:
sounds_failed.append("(\"" + str(sound[0]) + "\" : \"" + str(sound[1]) + "\") " + str(e)) # + str(url) + " "
else:
jsonResponse = json.loads(freesoundResponse.read().decode("utf-8"))
# metadata one-liners
database.append({
'soundName' : jsonResponse['name'],
'soundLink' : jsonResponse['url'],
'userName' : jsonResponse['username'],
'userLink' : "http://"+"/".join(jsonResponse['url'].split("/")[2:5]),
'licenseName': getLicenseName(jsonResponse['license']),
'licenseLink': jsonResponse['license']
})
# keep track of users and licenses involved
allUserNames.add(jsonResponse['username'])
allLicenseNames.add(getLicenseName(jsonResponse['license']))
# for all licenses, in order of unknown, by-nc, sampling+, by, cc0
# NEEDS UPDATING PROBABLY FOR CCBY4.0
orderedLicenseNames = [
"Unknown License",
"CC-BY-NC 3.0",
"CC-Sampling+",
"CC-BY 3.0",
"CC0"
]
credits = ""
creditsHTML = ""
# order credits by most strict licenses at the top
for orderedLicenseName in orderedLicenseNames:
# for each existing license
if orderedLicenseName in allLicenseNames:
firstLicense = True
userNeeded = False #since we loop over all users, we need to know when one actually matches for ending user credits
tmpUserName = ""
tmpUserLink = ""
# for each existing user
for userName in allUserNames:
# for each sound
for item in database:
if ((item['userName'] == userName) and (item['licenseName'] == orderedLicenseName)):
userNeeded = True
tmpUserName = item['userName']
tmpUserLink = item['userLink']
if firstLicense:
credits = credits + "<br>Sounds under " + item['licenseName'] + " ( " + item['licenseLink'] + " ):<br>"
creditsHTML = creditsHTML + "<br>Sounds under <a href='" + item['licenseLink'] + "'>" + item['licenseName'] + "</a>:<br>"
firstLicense = False
credits = credits + "\n" + item['soundName'] + " ( " + getShortLink(item['soundLink']) + " ), "
creditsHTML = creditsHTML + "\n<a href='" + getShortLink(item['soundLink']) + "'>" + item['soundName'] + "</a>, "
if userNeeded:
creditsHTML = creditsHTML[:-2] + " by <a href='" + getShortLink(tmpUserLink) + "'>" + tmpUserName + "</a>\n<br>\n"
credits = credits[:-2] + " by " + tmpUserName + " ( " + getShortLink(tmpUserLink) + " )\n<br>\n"
userNeeded = False
# chop off leading and tailing break
creditsHTML = creditsHTML[4:][:-5]
credits = credits[4:][:-5]
# simple credits
allUserNamesSingle = list(set(allUserNames))
allUserNamesString = ', '.join(allUserNamesSingle)
allFailedString = '<br>'.join(sounds_failed)
allDuplicateString = '<br>'.join(sounds_duplicate)
html_content = """
<h1>Freesound Super Credits Results</h1>
<p>Should there be issues with the results, please report to qubodup@gmail.com</p>
<p>Use your browser "back" button/function to return to your input (might not work in any browser) or <a href="%s">start new query</a></p>
""" % (url_for('hello_person'))
if (len(sounds_failed) > 0):
html_content = html_content + """
<div class='error'>
<h2>Failed items</h2>
<p>%s</p>
</div>
""" % (allFailedString)
if (len(sounds_duplicate) > 0):
html_content = html_content + """
<div class='warning'>
<h2>Duplicate items</h2>
<p>%s</p>
</div>
""" % (allDuplicateString)
html_content = html_content + """
<h2>Plaintext credits</h2>
<p>%s</p>
<h2>HTML credits (WYSIWYG)</h2>
<p>%s</p>
<h2>HTML credits (code)</h2>
<textarea>%s</textarea>
<h2>Additional minimal credits</h2>
<p>Simple comma-separated list of all usernames:</p>
<p>%s</p>
""" % (credits, creditsHTML, creditsHTML, allUserNamesString)
return html_header + html_content + html_footer
# Creates attribution html text
def attribution_construct_html(item):
return (
"<a href='" +
item.soundLink +
"'>" +
item.soundName +
"</a> by <a href='" +
item.userLink +
"'>" +
item.userName +
"</a>" +
"\n" +
item.licenseName +
"<br>" # since this is for HTML output
)
# Creates attribution plain text
def attribution_construct(item):
item.sndAttribution = (
"By " +
item.userName +
" " +
item.sndUserUrl +
" under " +
item.sndLicense +
"\n" +
item.sndTitleOrg +
": " +
item.licenseName +
"<br>" # since this is for HTML output
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment