Created
January 18, 2023 22:01
-
-
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/
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 & text author attribution & 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) & plaintext (YouTube descriptions and readme files).</p> | |
<p>If this tool is inconvenient, please write how you would prefer it to [email protected], 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& | |
<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 [email protected]</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