From f4621b8ce1f573411d6891ae99f9e32cb3eaacb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?tr=C3=A9meur?= Date: Sun, 24 Mar 2024 12:50:30 +0000 Subject: [PATCH 01/10] Update prompt scraper to build an HTML page with the prompts --- .gitignore | 2 +- prompts.css | 47 +++++++++++++++++++++++++++++++++++++ promptscrape.py | 61 ++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 103 insertions(+), 7 deletions(-) create mode 100644 prompts.css diff --git a/.gitignore b/.gitignore index 7d6d9e7..85d00a6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ -ficheader.html +prompts.html prompts.org __pycache__/* \ No newline at end of file diff --git a/prompts.css b/prompts.css new file mode 100644 index 0000000..8a4ae53 --- /dev/null +++ b/prompts.css @@ -0,0 +1,47 @@ +html { + text-transform: lowercase; + color: #808080; + background-color: #d5d5ef; + /* opacity: 0.8; */ + background-image: repeating-radial-gradient( circle at 0 0, transparent 0, #d5d5ef 28px ), repeating-linear-gradient( #cfcfe755, #cfcfe7 ); + font-family: "Poppins", sans-serif; +} + +a { + color: #999999; + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +body { + margin: 0 auto; + max-width: 800px; +} + +div.promptwrapper > div.promptcomm { + border: 1px solid #808080; + padding: 0 5px; +} + +div.promptcomm:first-of-type { + border-radius: 5px 5px 0 0; +} + +div.promptcomm:last-of-type { + border-radius: 0 0 5px 5px; +} + +div.timestamp { + text-align: right; +} + +.prompt { + font-weight: 700; +} + +.notes { + color: #b3b3b3; +} diff --git a/promptscrape.py b/promptscrape.py index b4000d6..bfddbe7 100644 --- a/promptscrape.py +++ b/promptscrape.py @@ -18,6 +18,8 @@ today = int(date.today().strftime("%d")) month = str(date.today().strftime("%B")) monthstring = ".*" + month + ".*" +prompts = [] + try: cent = "https://100words.dreamwidth.org/tag/!prompt?style=light&tag=%21prompt" centpage = requests.get(cent) @@ -33,6 +35,7 @@ try: centtheprompt = centprompttext.find("strong") print("100words (100 words): \033[1m" + centtheprompt.text.lower() + "\033[0m (" + centprompt + ")\n") thefile.write("- [[" + centprompt + "][100words]] (100 words): *" + centtheprompt.text.lower() + "*\n") + prompts.append({"source":"100words","type":"comm","notes":"100 words","prompt":centtheprompt.text.lower(),"url":centprompt}) except: pass @@ -88,6 +91,7 @@ try: adstrippable = adstrippable[1:] print("anythingdrabble (100, 200, 300, 400, or 500 words): \033[1m" + adstrippable.lower() + "\033[0m (" + adprompt + ")\n") thefile.write("- [[" + adprompt + "][anythingdrabble]] (100, 200, 300, 400, or 500 words): *" + adstrippable.lower() + "*\n") + prompts.append({"source":"anythingdrabble","type":"comm","notes":"100, 200, 300, 400, or 500 words","prompt":adstrippable.lower(),"url":adprompt}) except: pass @@ -106,6 +110,7 @@ try: dovetheprompt = doveprompttext.find("i") print("dove-drabbles (any): \033[1m" + dovetheprompt.text.lower() + "\033[0m (" + doveprompt + ")\n") thefile.write("- [[" + doveprompt + "][dove-drabbles]] (any): *" + dovetheprompt.text.lower() + "*\n") + prompts.append({"source":"dove-drabbles","type":"comm","notes":"any length","prompt":dovetheprompt.text.lower(),"url":doveprompt}) except: pass @@ -126,7 +131,13 @@ try: zonetheprompt = zoneprompttext.find("strong") print("drabble-zone (100 or 200 words): \033[1m" + zonetheprompt.text.lower() + "\033[0m (" + zoneprompt + ")\n") thefile.write("- [[" + zoneprompt + "][drabble-zone]] (100 or 200 words): *" + zonetheprompt.text.lower() + "*\n") - + prompts.append({"source":"drabble-zone","type":"comm","notes":"100 or 200 words","prompt":zonetheprompt.text.lower(),"url":zoneprompt}) +except: + pass + +try: + with requests.Session() as s: + response = s.post(login_url , data) emotion = "https://emotion100.dreamwidth.org/tag/*modpost?style=light&tag=%2Amodpost" emotionpage = s.get(emotion) emotionsoup = BeautifulSoup(emotionpage.content, "html.parser") @@ -141,6 +152,7 @@ try: emotiontheprompt = emotionprompttext.find_all("span")[-1] print("emotion100 (100 words or a multiple of 100): \033[1m" + emotiontheprompt.text.lower() + "\033[0m (" + emotionprompt + ")\n") thefile.write("- [[" + emotionprompt + "][emotion100]] (100 words or a multiple of 100): *" + emotiontheprompt.text.lower() + "*\n") + prompts.append({"source":"emotion100","type":"comm","notes":"100 words or a multiple of 100","prompt":emotiontheprompt.text.lower(),"url":emotionprompt}) except: pass @@ -184,6 +196,7 @@ try: ffaformat = "; ".join(ffacentnew) print("fail-fandomanon (any): \033[1m" + ffaformat.lower() + "\033[0m (" + ffaprompt + ")\n") thefile.write("- [[" + ffaprompt + "][fail-fandomanon]] (any): *" + ffaformat.lower() + "*\n") + prompts.append({"source":"fail-fandomanon","type":"comm","notes":"any length","prompt":ffacentnew,"url":ffaprompt}) except: pass @@ -206,6 +219,7 @@ try: fandomtheprompt = fandomprompttext.find("td") print("fandomweekly (any, competitive): \033[1m" + fandomtheprompt.text.lower() + "\033[0m (" + fandomprompt + ")\n") thefile.write("- [[" + fandomprompt + "][fandomweekly]] (any, competitive): *" + fandomtheprompt.text.lower() + "*\n") + prompts.append({"source":"fandomweekly","type":"comm","notes":"any length, competitive","prompt":fandomtheprompt.text.lower(),"url":fandomprompt}) except: pass @@ -224,6 +238,7 @@ try: flashtheprompt = flashprompttext.find("center") print("fan-flashworks (any, can’t post elsewhere until round is closed): \033[1m" + flashtheprompt.text.lower() + "\033[0m (" + flashprompt + ")\n") thefile.write("- [[" + flashprompt + "][fan-flashworks]] (any, can’t post elsewhere until round is closed): *" + flashtheprompt.text.lower() + "*\n") + prompts.append({"source":"fan-flashworks","type":"comm","notes":"any length, can’t post elsewhere until round is closed","prompt":flashtheprompt.text.lower(),"url":flashprompt}) except: pass @@ -264,6 +279,7 @@ try: fffclittleprompttext = fffclittlepromptsoup.find("h3") print("fffc little special (at least 100 words): \033[1m" + fffclittleprompttext.text.lower() + "\033[0m (" + fffclittleprompt + ")\n") thefile.write("- [[" + fffclittleprompt + "][fffc little special]] (at least 100 words): *" + fffclittleprompttext.text.lower() + "*\n") + prompts.append({"source":"fffc","type":"comm","notes":"at least 100 words","prompt":fffclittleprompttext.text.lower(),"url":fffclittleprompt,"challenge":"little special"}) fffcmadnessprompts = fffcsoup.find_all("h3", string=lambda text: "froday madness" in text.lower()) fffcmadnesssubsoup = BeautifulSoup(str(fffcmadnessprompts[0]), "html.parser") fffcmadnessurl = fffcmadnesssubsoup.find("a") @@ -275,6 +291,7 @@ try: fffcmadnesstheprompt = fffcmadnessprompttext.find("b") print("fffc madness (at least 2000 words): \033[1m" + fffcmadnesstheprompt.text.lower() + "\033[0m (" + fffcmadnessprompt + ")\n") thefile.write("- [[" + fffcmadnessprompt + "][fffc madness]] (at least 2000 words): *" + fffcmadnesstheprompt.text.lower() + "*\n") + prompts.append({"source":"fffc","type":"comm","notes":"at least 2000 words","prompt":fffcmadnesstheprompt.text.lower(),"url":fffcmadnessprompt,"challenge":"froday madness"}) fffcmonthlyprompts = fffcsoup.find_all("h3", string=re.compile(monthstring)) fffcmonthlysubsoup = BeautifulSoup(str(fffcmonthlyprompts[0]), "html.parser") fffcmonthlyurl = fffcmonthlysubsoup.find("a") @@ -285,6 +302,7 @@ try: fffcmonthlyprompttext = fffcmonthlypromptsoup.find("h3") print("fffc monthly special (usually at least 500 words): \033[1m" + fffcmonthlyprompttext.text.lower() + "\033[0m (" + fffcmonthlyprompt + ")\n") thefile.write("- [[" + fffcmonthlyprompt + "][fffc monthly special]] (usually at least 500 words): *" + fffcmonthlyprompttext.text.lower() + "*\n") + prompts.append({"source":"fffc","type":"comm","notes":"usually at least 500 words","prompt":fffcmonthlyprompttext.text.lower(),"url":fffcmonthlyprompt,"challenge":"monthly challenge"}) fffcregularprompts = fffcsoup.find_all("h3", string=lambda text: "regular challenge" in text.lower()) fffcregularsubsoup = BeautifulSoup(str(fffcregularprompts[0]), "html.parser") fffcregularurl = fffcregularsubsoup.find("a") @@ -296,6 +314,7 @@ try: fffcregulartheprompt = fffcregularprompttext.find("b") print("fffc regular challenge (at least 100 words): \033[1m" + fffcregulartheprompt.text.lower() + "\033[0m (" + fffcregularprompt + ")\n") thefile.write("- [[" + fffcregularprompt + "][fffc regular challenge]] (at least 100 words): *" + fffcregulartheprompt.text.lower() + "*\n") + prompts.append({"source":"fffc","type":"comm","notes":"at least 100 words","prompt":fffcregulartheprompt.text.lower(),"url":fffcregularprompt,"challenge":"regular challenge"}) except: pass @@ -314,6 +333,7 @@ try: ficlettheprompt = ficletprompttext.find("a") print("ficlet-zone (any): \033[1m" + ficlettheprompt.text.lower() + "\033[0m (" + ficletprompt + ")\n") thefile.write("- [[" + ficletprompt + "][ficlet-zone]] (any): *" + ficlettheprompt.text.lower() + "*\n") + prompts.append({"source":"ficlet-zone","type":"comm","notes":"any length","prompt":ficlettheprompt.text.lower(),"url":ficletprompt}) except: pass @@ -340,6 +360,7 @@ try: hourlypromptthishour = str(hourlypromptmedian[0])[5:-5] print("hourlyprompts (any): \033[1m" + hourlypromptthishour.lower() + "\033[0m (" + hourlyprompt + ")\n") thefile.write("- [[" + hourlyprompt + "][hourlyprompts]] (any): *" + hourlypromptthishour.lower() + "*\n") + prompts.append({"source":"hourlyprompts","type":"comm","notes":"any length","prompt":hourlypromptthishour.lower(),"url":hourlyprompt}) except: pass @@ -381,6 +402,7 @@ if themonth != 4 and themonth != 8 and themonth != 12: ssbingofinal = "; ".join(ssbingoclean).lower() print("sweet and short bingo (up to 500 words, separate or combined): \033[1m" + ssbingofinal + "\033[0m (" + ssbingoprompt + ")\n") thefile.write("- [[" + ssbingoprompt + "][sweet and short bingo]] (up to 500 words, separate or combined): *" + ssbingofinal + "*\n") + prompts.append({"source":"sweetandshort","type":"comm","notes":"up to 500 words, separate or combined","prompt":ssbingoclean,"url":ssbingoprompt,"challenge":"bingo"}) except: pass @@ -398,18 +420,18 @@ if themonth != 4 and themonth != 8 and themonth != 12: ssquickypromptnew = (ssquickyurl["href"]) ssquickypromptpage = requests.get(ssquickypromptnew) ssquickypromptsoup = BeautifulSoup(ssquickypromptpage.content, "html.parser") - promptcatch = ".*New Prompts Here" - # ssquickytheprompt = ssquickypromptsoup.find_all("h4",string = re.compile(promptcatch)) ssquickytheprompt = ssquickypromptsoup.find_all(class_="comment") ssquickycomments = [] for comment in ssquickytheprompt: - if re.search("New Prompts Here",str(comment)): + if re.search("new prompts here",str(comment),re.IGNORECASE): commenttext = re.findall(r"
",str(comment)) - commentprompt = re.sub("<.*?>","",str(commenttext)) + commentprompt = re.sub("<.*?>","",str(commenttext)).replace("\\'","'") ssquickycomments.append(str(commentprompt)[2:-2]) + ssquickycomments = ssquickycomments[1:] ssquickycprompt = "; ".join(ssquickycomments) print("sweet and short comment quicky (up to 100 words): \033[1m" + ssquickycprompt.lower() + "\033[0m (" + ssquickyprompt + ")\n") thefile.write("- [[" + ssquickyprompt + "][sweet and short comment quicky]] (up to 100 words): *" + ssquickycprompt.lower() + "*\n") + prompts.append({"source":"sweetandshort","type":"comm","notes":"up to 100 words","prompt":ssquickycomments,"url":ssquickyprompt,"challenge":"comment quicky"}) elif alternate == "picture": sspicture = "https://sweetandshort.dreamwidth.org/tag/!new+challenge,challenge:+picture+prompt+fun?mode=and&style=light&tag=%21new+challenge,challenge:+picture+prompt+fun&mode=and" sspicturepage = requests.get(sspicture) @@ -425,6 +447,7 @@ if themonth != 4 and themonth != 8 and themonth != 12: sspictureprompttext = sspicturepromptsoup.find("h3") print("sweet and short picture prompts (up to 300 words): \033[1m" + sspictureprompttext.text.lower() + "\033[0m (" + sspictureprompt + ")\n") thefile.write("- [[" + sspictureprompt + "][sweet and short picture prompts]] (up to 300 words): *" + sspictureprompttext.text.lower() + "*\n") + prompts.append({"source":"sweetandshort","type":"comm","notes":"up to 300 words","prompt":sspictureprompttext.text.lower(),"url":sspictureprompts,"challenge":"picture prompt fun"}) except: pass @@ -447,6 +470,7 @@ if themonth != 4 and themonth != 8 and themonth != 12: ssmonthlypromptfinal = str(ssmonthlypromptstripthree)[2:-2] print("sweet and short monthly prompts (up to 500 words based on at least 10 prompts): \033[1m" + ssmonthlypromptfinal + "\033[0m (" + ssmonthlyprompt + ")\n") thefile.write("- [[" + ssmonthlyprompt + "][sweet and short monthly prompts]] (up to 500 words based on at least 10 prompts): *" + ssmonthlypromptfinal + "*\n") + prompts.append({"source":"sweetandshort","type":"comm","notes":"up to 500 words based on at least 10 prompts","prompt":ssmonthlypromptfinal,"url":ssmonthlyprompt,"challenge":"monthly prompt"}) except: pass @@ -468,7 +492,7 @@ if themonth != 4 and themonth != 8 and themonth != 12: ssonepromptfinal = re.sub("2. ","; ",ssonepromptstriptwo) print("sweet and short one sentence (up to 500 words, use one or both lines as the start and/or end): \033[1m" + ssonepromptfinal + "\033[0m (" + ssoneprompt + ")\n") thefile.write("- [[" + ssoneprompt + "][sweet and short one sentence]] (up to 500 words, use one or both lines as the start and/or end): *" + ssonepromptfinal + "*\n") - + prompts.append({"source":"sweetandshort","type":"comm","notes":"up to 500 words, use one or both lines as the start and/or end","prompt":ssonepromptfinal,"url":ssoneprompt,"challenge":"only one"}) except: pass @@ -487,5 +511,30 @@ try: vocabtheprompt = vocabprompttext.find("strong") print("vocab-drabbles (50–500 words): \033[1m" + vocabtheprompt.text.lower() + "\033[0m (" + vocabprompt + ")\n") thefile.write("- [[" + vocabprompt + "][vocab-drabbles]] (50–500 words): *" + vocabtheprompt.text.lower() + "*\n") + prompts.append({"source":"vocab-drabbles","type":"comm","notes":"50–500 words","prompt":vocabtheprompt.text.lower(),"url":vocabprompt}) except: pass + + +if os.path.exists("prompts.html"): + os.remove("prompts.html") + +htmlfile = open("prompts.html", "a") +htmlfile.write("\n\n \n \n \n \n \n \n \n \n Multifandom prompt communities on DW\n \n \n

Multifandom prompt communities on DW

\n
\n") +for prompt in prompts: + htmlfile.write("

\"[community" + prompt["source"].replace("-","_") + "") + try: + if prompt["challenge"]: + htmlfile.write(" " + prompt["challenge"]) + except: + pass + if type(prompt["prompt"]) == list: + htmlfile.write(": prompt post (" + prompt["notes"] + ")

\n
    \n") + for theprompt in prompt["prompt"]: + htmlfile.write("
  • " + theprompt + "
  • \n") + htmlfile.write("
") + else: + htmlfile.write(": " + prompt["prompt"] + " (" + prompt["notes"] + ")

") + htmlfile.write("
\n") +htmlfile.write("
\n

Generated " + datetime.now().strftime("%H:%M (UK time), %-d %B %Y") + "

\n \n") +htmlfile.close() From 9181590385ddfd8f334f4603ab4a5b59565cf69b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?tr=C3=A9meur?= Date: Fri, 29 Mar 2024 11:01:47 +0000 Subject: [PATCH 02/10] Add FF Yuletide checker --- README.org | 1 + ffyuletide.py | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 ffyuletide.py diff --git a/README.org b/README.org index c11e52b..5df4b6e 100644 --- a/README.org +++ b/README.org @@ -1,6 +1,7 @@ * Python utilities for personal and fannish purposes - =ao3scrape.py= – downloads all an author’s works from AO3 (notes [[https://tobli.dreamwidth.org/45337.html][here]]) - =cellopractice.py= – selects some exercises from Walter Mengler’s /Fit in 15 Minutes/, according to the author’s recommendations +- =ffyuletide.py= – checks which Final Fantasy fandoms are Yuletide-eligible - =peterson.py= – questions everything - =promptscrape.py= – scrapes Dreamwidth writing challenge communities for prompts - =randomline.py= – returns a random line from a file diff --git a/ffyuletide.py b/ffyuletide.py new file mode 100644 index 0000000..c94a04a --- /dev/null +++ b/ffyuletide.py @@ -0,0 +1,62 @@ +import re, requests, time +from bs4 import BeautifulSoup + +# grab subtags of "final fantasy series" + +series = "https://archiveofourown.org/tags/Final%20Fantasy%20Series" +seriespage = requests.get(series) +seriessoup = BeautifulSoup(seriespage.content,"html.parser") +fandoms = seriessoup.find(class_="sub").find("ul",{ "class" : "tree" }).findAll("li", recursive=False) + +# open search page with filters applied + +filterpage = "https://archiveofourown.org/works?work_search%5Bsort_column%5D=revised_at&work_search%5Bother_tag_names%5D=&work_search%5Bexcluded_tag_names%5D=&work_search%5Bcrossover%5D=&work_search%5Bcomplete%5D=T&work_search%5Bwords_from%5D=1000&work_search%5Bwords_to%5D=&work_search%5Bdate_from%5D=&work_search%5Bdate_to%5D=&work_search%5Bquery%5D=&work_search%5Blanguage_id%5D=en&commit=Sort+and+Filter&tag_id=" +eligible = [] +ineligible = [] +with requests.Session() as s: + loginpage = s.get("https://archiveofourown.org/users/login") + loginsoup = BeautifulSoup(loginpage.content,"html.parser") + token = (loginsoup.find('form', class_='new_user') + .find('input', attrs={'name': 'authenticity_token'}) + .get('value')) + payload = {'user[login]': "translinkni", + 'user[password]': "fakeapi", + 'user[remember_me]': '1', + 'authenticity_token': token + } + post = s.post("https://archiveofourown.org/users/login",data=payload) + for fandom in fandoms: + time.sleep(3) + tagurl = (str(fandom.find("a")["href"]))[6:] + tagname = str(fandom.find(class_="tag").text) + print("Checking " + tagname + " (" + str(fandoms.index(fandom) + 1) + " of " + str(len(fandoms)) + ")") + tagpage = s.get(filterpage + tagurl) + tagsoup = BeautifulSoup(tagpage.content,"html.parser") + + # get the number + + heading = (tagsoup.find("h2",class_="heading")).text + stripone = re.sub("\n","",heading) + striptwo = re.sub(" Work.*","",stripone) + stripthree = re.sub(".* of ","",striptwo) + stripfour = re.sub(",","",stripthree) + workcount = int(stripfour) + + # if number < 1000, add to eligible list + + fandomdict = {"name":tagname,"count":workcount} + + if workcount < 1000: + eligible.append(fandomdict) + else: + ineligible.append(fandomdict) + +eligible = sorted(eligible,key=lambda d: d["count"],reverse=True) +ineligible = sorted(ineligible,key=lambda d: d["count"],reverse=True) + +print("\nCurrently eligible:\n") +for fandom in eligible: + print(fandom["name"] + " (" + str(fandom["count"]) + ")") +print("\nIneligible:\n") +for fandom in ineligible: + print(fandom["name"] + " (" + str(fandom["count"]) + ")") From ed6f42a2aeb68733158453af4c042ce8289fcbaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?tr=C3=A9meur?= Date: Sat, 6 Apr 2024 19:23:03 +0100 Subject: [PATCH 03/10] Account for a couple of changes to DW prompt communities --- prompts.css | 2 +- promptscrape.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/prompts.css b/prompts.css index 8a4ae53..6f49399 100644 --- a/prompts.css +++ b/prompts.css @@ -3,7 +3,7 @@ html { color: #808080; background-color: #d5d5ef; /* opacity: 0.8; */ - background-image: repeating-radial-gradient( circle at 0 0, transparent 0, #d5d5ef 28px ), repeating-linear-gradient( #cfcfe755, #cfcfe7 ); + background-image: repeating-radial-gradient( circle at 0 0, transparent 0, #d5d5ef 28px ), repeating-linear-gradient( #cfcfe5, #cfcfe7 ); font-family: "Poppins", sans-serif; } diff --git a/promptscrape.py b/promptscrape.py index bfddbe7..8c155cb 100644 --- a/promptscrape.py +++ b/promptscrape.py @@ -99,7 +99,7 @@ try: dove = "https://dove-drabbles.dreamwidth.org/?style=light" dovepage = requests.get(dove) dovesoup = BeautifulSoup(dovepage.content, "html.parser") - doveprompts = dovesoup.find_all("h3", string=lambda text: "prompt post" in text.lower()) + doveprompts = dovesoup.find_all("h3", string=lambda text: "prompt" in text.lower()) dovesubsoup = BeautifulSoup(str(doveprompts[0]), "html.parser") doveurl = dovesubsoup.find("a") doveprompt = (doveurl["href"]) @@ -128,7 +128,7 @@ try: zonepromptpage = s.get(zonepromptnew) zonepromptsoup = BeautifulSoup(zonepromptpage.content, "html.parser") zoneprompttext = zonepromptsoup.find(class_="entry-content") - zonetheprompt = zoneprompttext.find("strong") + zonetheprompt = zoneprompttext.find("div") print("drabble-zone (100 or 200 words): \033[1m" + zonetheprompt.text.lower() + "\033[0m (" + zoneprompt + ")\n") thefile.write("- [[" + zoneprompt + "][drabble-zone]] (100 or 200 words): *" + zonetheprompt.text.lower() + "*\n") prompts.append({"source":"drabble-zone","type":"comm","notes":"100 or 200 words","prompt":zonetheprompt.text.lower(),"url":zoneprompt}) From 7fb654821eb4c961df7513cc225694afb7490d42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?tr=C3=A9meur?= Date: Sat, 11 May 2024 20:36:58 +0100 Subject: [PATCH 04/10] Add femslashfete to the prompt scraper --- promptscrape.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/promptscrape.py b/promptscrape.py index 8c155cb..047b255 100644 --- a/promptscrape.py +++ b/promptscrape.py @@ -242,6 +242,27 @@ try: except: pass +try: + with requests.Session() as s: + response = s.post(login_url , data) + fsf = "https://femslashfete.dreamwidth.org/tag/admin?style=light&tag=admin" + fsfpage = s.get(fsf) + fsfsoup = BeautifulSoup(fsfpage.content, "html.parser") + fsfprompts = fsfsoup.find_all("h3", string=lambda text: "challenge" in text.lower()) + fsfsubsoup = BeautifulSoup(str(fsfprompts[0]), "html.parser") + fsfurl = fsfsubsoup.find("a") + fsfprompt = (fsfurl["href"]) + fsfpromptnew = (fsfurl["href"] + "?style=light") + fsfpromptpage = s.get(fsfpromptnew) + fsfpromptsoup = BeautifulSoup(fsfpromptpage.content, "html.parser") + fsfprompttext = fsfpromptsoup.find(class_="entry-content") + fsftheprompt = fsfprompttext.find("b") + print("femslashfete (at least 100 words, must be femslash): \033[1m" + fsftheprompt.text.lower() + "\033[0m (" + fsfprompt + ")\n") + thefile.write("- [[" + fsfprompt + "][femslashfete]] (at least 100 words, must be femslash): *" + fsftheprompt.text.lower() + "*\n") + prompts.append({"source":"femslashfete","type":"comm","notes":"at least 100 words, must be femslash","prompt":fsftheprompt.text.lower(),"url":fsfprompt}) +except: + pass + # seems dead # try: # femslash = "https://femslashficlets.dreamwidth.org/tag/challenges?style=light&tag=challenges" @@ -447,7 +468,7 @@ if themonth != 4 and themonth != 8 and themonth != 12: sspictureprompttext = sspicturepromptsoup.find("h3") print("sweet and short picture prompts (up to 300 words): \033[1m" + sspictureprompttext.text.lower() + "\033[0m (" + sspictureprompt + ")\n") thefile.write("- [[" + sspictureprompt + "][sweet and short picture prompts]] (up to 300 words): *" + sspictureprompttext.text.lower() + "*\n") - prompts.append({"source":"sweetandshort","type":"comm","notes":"up to 300 words","prompt":sspictureprompttext.text.lower(),"url":sspictureprompts,"challenge":"picture prompt fun"}) + prompts.append({"source":"sweetandshort","type":"comm","notes":"up to 300 words","prompt":sspictureprompttext.text.lower(),"url":sspictureprompt,"challenge":"picture prompt fun"}) except: pass From cc87be8be9a52935be78cd37a132ab0b924afc81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?tr=C3=A9meur?= Date: Sat, 11 May 2024 20:38:29 +0100 Subject: [PATCH 05/10] Remove link to deleted DW post --- README.org | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.org b/README.org index 5df4b6e..d5d7809 100644 --- a/README.org +++ b/README.org @@ -1,5 +1,5 @@ * Python utilities for personal and fannish purposes -- =ao3scrape.py= – downloads all an author’s works from AO3 (notes [[https://tobli.dreamwidth.org/45337.html][here]]) +- =ao3scrape.py= – downloads all an author’s works from AO3 - =cellopractice.py= – selects some exercises from Walter Mengler’s /Fit in 15 Minutes/, according to the author’s recommendations - =ffyuletide.py= – checks which Final Fantasy fandoms are Yuletide-eligible - =peterson.py= – questions everything From 3ac23d3ed26c908a328b42c45d53947584f7cd54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?tr=C3=A9meur?= Date: Sat, 29 Jun 2024 22:26:26 +0100 Subject: [PATCH 06/10] Add script for scrobbling physical albums --- .gitignore | 1 + scrobble.py | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 scrobble.py diff --git a/.gitignore b/.gitignore index 85d00a6..5abfae0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +albums.py prompts.html prompts.org __pycache__/* \ No newline at end of file diff --git a/scrobble.py b/scrobble.py new file mode 100644 index 0000000..1916b6a --- /dev/null +++ b/scrobble.py @@ -0,0 +1,119 @@ +import pylast,random,re,sys,time +import albums + +network = pylast.LastFMNetwork(api_key=albums.apikey, api_secret=albums.apisecret, username="litrovers", password_hash=pylast.md5(albums.pw)) # https://input.sh/scrobbling-live-sets-into-last-fm-using-python/ + +thealbums = sorted(albums.albums,key=lambda d: d["name"]) +# albums = sorted(albums,key=lambda d: d["artist"]) + +def countdown(t): # https://stackoverflow.com/a/25189629 + while t: + mins, secs = divmod(t, 60) + timeformat = '{:02d}:{:02d}'.format(mins, secs) + print(timeformat, end='\r') + time.sleep(1) + t -= 1 + +def scrobble(thealbum): + for album in thealbums: + if thealbum == album["code"]: + i = 0 + for tracklist in album["tracks"]: + i += 1 + for item in tracklist: + if " :: " in item: + theartist = re.sub(" :: .*","",item) + thetrack = re.sub(".* :: ","",item) + else: + theartist = album["artist"] + thetrack = item + # last_api_call = network.scrobble(theartist,thetrack,int(time.time())) + print("Scrobbled " + item) + # countdown(tracklist[item]) + if i < len(album["tracks"]): + input("Press enter after changing side") + +def query_yes_no(question, default="yes"): # https://code.activestate.com/recipes/577058/ + """Ask a yes/no question via raw_input() and return their answer. + + "question" is a string that is presented to the user. + "default" is the presumed answer if the user just hits . + It must be "yes" (the default), "no" or None (meaning + an answer is required of the user). + + The "answer" return value is one of "yes" or "no". + """ + valid = {"yes":"yes", "y":"yes", "ye":"yes", + "no":"no", "n":"no"} + if default == None: + prompt = " [y/n] " + elif default == "yes": + prompt = " [Y/n] " + elif default == "no": + prompt = " [y/N] " + else: + raise ValueError("invalid default answer: '%s'" % default) + while 1: + sys.stdout.write(question + prompt) + choice = input().lower() + if default is not None and choice == '': + return default + elif choice in valid.keys(): + return valid[choice] + else: + sys.stdout.write("Please respond with 'yes' or 'no' "\ + "(or 'y' or 'n').\n") + +def selectFromDict(options, name): # https://stackoverflow.com/a/64536882 + index = 0 + indexValidList = [] + print('Select an ' + name + ':') + for optionName in options: + index = index + 1 + indexValidList.extend([options[optionName]]) + print(str(index) + ') ' + optionName) + inputValid = False + while not inputValid: + inputRaw = input(name + ': ') + inputNo = int(inputRaw) - 1 + if inputNo > -1 and inputNo < len(indexValidList): + selected = indexValidList[inputNo] + # print('Selected ' + name + ': ' + selected) + inputValid = True + break + else: + print('Please select a valid ' + name + ' number') + return selected + +def choosealbum(): + randomer = query_yes_no("Pick an album for me?","no") + if randomer == "yes": + revision = "yes" + while revision == "yes": + chosen = random.choice(thealbums) + thechosen = chosen["code"] + try: + print(chosen["album artist"] + ": " + chosen["name"]) + except: + print(chosen["artist"] + ": " + chosen["name"]) + revision = query_yes_no("Roll again?","no") + else: + process = False + while process == False: + firstletter = input("Type the first letter of the album name\n") + letteralbums = {} + for album in thealbums: + process = True + if album["name"][0].lower() == str(firstletter): + try: + letteralbums[album["name"] + " (" + album["album artist"] + ")"] = album["code"] + except: + letteralbums[album["name"] + " (" + album["artist"] + ")"] = album["code"] + if len(letteralbums) == 0: + process = False + print("No albums found") + thechosen = selectFromDict(letteralbums, "album") + scrobble(thechosen) + +if __name__ == "__main__": + choosealbum() From e6d14a0e500c5a3d0c8a937de6d9bd4d77441ebe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?tr=C3=A9meur?= Date: Sat, 29 Jun 2024 22:29:42 +0100 Subject: [PATCH 07/10] Fuck --- scrobble.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scrobble.py b/scrobble.py index 1916b6a..84f5536 100644 --- a/scrobble.py +++ b/scrobble.py @@ -27,9 +27,9 @@ def scrobble(thealbum): else: theartist = album["artist"] thetrack = item - # last_api_call = network.scrobble(theartist,thetrack,int(time.time())) + last_api_call = network.scrobble(theartist,thetrack,int(time.time())) print("Scrobbled " + item) - # countdown(tracklist[item]) + countdown(tracklist[item]) if i < len(album["tracks"]): input("Press enter after changing side") From 3d283da0f777910d35d62b0648f1627ce050eb50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?tr=C3=A9meur?= Date: Wed, 3 Jul 2024 23:09:07 +0100 Subject: [PATCH 08/10] =?UTF-8?q?Add=20option=20for=20tracks=20that=20won?= =?UTF-8?q?=E2=80=99t=20be=20scrobbled?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scrobble.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/scrobble.py b/scrobble.py index 84f5536..40aa179 100644 --- a/scrobble.py +++ b/scrobble.py @@ -27,8 +27,11 @@ def scrobble(thealbum): else: theartist = album["artist"] thetrack = item - last_api_call = network.scrobble(theartist,thetrack,int(time.time())) - print("Scrobbled " + item) + if theartist == "noscrob": + print("Skipped " + thetrack) + else: + last_api_call = network.scrobble(theartist,thetrack,int(time.time())) + print("Scrobbled " + item) countdown(tracklist[item]) if i < len(album["tracks"]): input("Press enter after changing side") From e6043132f8939db5c8fc0bc388fbf84ff6e6e9a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?tr=C3=A9meur?= Date: Sun, 25 Aug 2024 16:34:59 +0100 Subject: [PATCH 09/10] =?UTF-8?q?Add=20script=20for=20reviewing=20previous?= =?UTF-8?q?=20years=E2=80=99=20activities?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- otd.py | 19 +++++++++++++++++++ scrobble.py | 14 +++++++++----- 2 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 otd.py diff --git a/otd.py b/otd.py new file mode 100644 index 0000000..713d2d2 --- /dev/null +++ b/otd.py @@ -0,0 +1,19 @@ +import datetime,os + +year = int(datetime.datetime.strftime(datetime.datetime.today(),"%Y")) +monthstring = datetime.datetime.strftime(datetime.datetime.today(),"%m") +datestring = datetime.datetime.strftime(datetime.datetime.today(),"%d") + +fileplace = "/home/mdd/Documents/drive/org/journal/" + +thisyear = year + +while year > 1993: + year -= 1 + target = fileplace + str(year) + "/" + monthstring + "/" + str(year) + "-" + monthstring + "-" + datestring + ".org" + if os.path.exists(target): + if year < thisyear -1: + print("Press enter to continue") + input() + print(open(target,"r").read()) + diff --git a/scrobble.py b/scrobble.py index 40aa179..32db791 100644 --- a/scrobble.py +++ b/scrobble.py @@ -8,9 +8,9 @@ thealbums = sorted(albums.albums,key=lambda d: d["name"]) def countdown(t): # https://stackoverflow.com/a/25189629 while t: - mins, secs = divmod(t, 60) - timeformat = '{:02d}:{:02d}'.format(mins, secs) - print(timeformat, end='\r') + mins, secs = divmod(t,60) + timeformat = '{:02d}:{:02d}'.format(mins,secs) + print("> " + timeformat,end='\r') time.sleep(1) t -= 1 @@ -30,8 +30,12 @@ def scrobble(thealbum): if theartist == "noscrob": print("Skipped " + thetrack) else: - last_api_call = network.scrobble(theartist,thetrack,int(time.time())) - print("Scrobbled " + item) + if tracklist[item] > 29: + last_api_call = network.scrobble(theartist,thetrack,int(time.time())) + print("Scrobbled " + thetrack) + else: + print("Skipped " + thetrack) + last_api_call = network.update_now_playing(theartist,thetrack,duration=tracklist[item]) countdown(tracklist[item]) if i < len(album["tracks"]): input("Press enter after changing side") From 44a6ddc5f1486eb6cb11b33f53d6692e6e3fe2dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?tr=C3=A9meur?= Date: Sat, 31 Aug 2024 10:02:54 +0100 Subject: [PATCH 10/10] Attempt to add pleroma scrobble --- scrobble.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scrobble.py b/scrobble.py index 32db791..ba2ae6d 100644 --- a/scrobble.py +++ b/scrobble.py @@ -1,4 +1,4 @@ -import pylast,random,re,sys,time +import pylast,random,re,sys,time,requests import albums network = pylast.LastFMNetwork(api_key=albums.apikey, api_secret=albums.apisecret, username="litrovers", password_hash=pylast.md5(albums.pw)) # https://input.sh/scrobbling-live-sets-into-last-fm-using-python/ @@ -32,6 +32,10 @@ def scrobble(thealbum): else: if tracklist[item] > 29: last_api_call = network.scrobble(theartist,thetrack,int(time.time())) + try: + requests.post("https://ple.praze.net/api/v1/pleroma/scrobble",data = {"artist":theartist,"length":int(time.time()),"title":thetrack},auth = ("tre",albums.plepass)) + except: + pass print("Scrobbled " + thetrack) else: print("Skipped " + thetrack)