add support for Archive of Our Own
This commit is contained in:
parent
d80045c5ba
commit
67206367ec
7 changed files with 705 additions and 1 deletions
catalog
common/static/scss
test_data
|
@ -363,6 +363,37 @@ class DoubanBookTestCase(TestCase):
|
|||
self.assertEqual(editions[1].display_title, "黄金时代")
|
||||
|
||||
|
||||
class AO3TestCase(TestCase):
|
||||
databases = "__all__"
|
||||
|
||||
def test_parse(self):
|
||||
t_type = IdType.AO3
|
||||
t_id = "2080878"
|
||||
t_url = "https://archiveofourown.org/works/2080878"
|
||||
t_url2 = "https://archiveofourown.org/works/2080878?test"
|
||||
p1 = SiteManager.get_site_by_url(t_url)
|
||||
p2 = SiteManager.get_site_by_url(t_url2)
|
||||
self.assertEqual(p1.url, t_url)
|
||||
self.assertEqual(p1.ID_TYPE, t_type)
|
||||
self.assertEqual(p1.id_value, t_id)
|
||||
self.assertEqual(p2.url, t_url)
|
||||
self.assertEqual(p2.ID_TYPE, t_type)
|
||||
self.assertEqual(p2.id_value, t_id)
|
||||
|
||||
@use_local_response
|
||||
def test_scrape(self):
|
||||
t_url = "https://archiveofourown.org/works/2080878"
|
||||
site = SiteManager.get_site_by_url(t_url)
|
||||
self.assertEqual(site.ready, False)
|
||||
site.get_resource_ready()
|
||||
self.assertEqual(site.ready, True)
|
||||
self.assertEqual(site.resource.site_name, SiteName.AO3)
|
||||
self.assertEqual(site.resource.id_type, IdType.AO3)
|
||||
self.assertEqual(site.resource.id_value, "2080878")
|
||||
self.assertEqual(site.resource.item.display_title, "I Am Groot")
|
||||
self.assertEqual(site.resource.item.author[0], "sherlocksmyth")
|
||||
|
||||
|
||||
class QidianTestCase(TestCase):
|
||||
databases = "__all__"
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@ class SiteName(models.TextChoices):
|
|||
Fediverse = "fedi", _("Fediverse") # type:ignore[reportCallIssue]
|
||||
Qidian = "qidian", _("Qidian") # type:ignore[reportCallIssue]
|
||||
Ypshuo = "ypshuo", _("Ypshuo") # type:ignore[reportCallIssue]
|
||||
AO3 = "ao3", _("Archive of Our Own") # type:ignore[reportCallIssue]
|
||||
|
||||
|
||||
class IdType(models.TextChoices):
|
||||
|
@ -115,6 +116,7 @@ class IdType(models.TextChoices):
|
|||
Fediverse = "fedi", _("Fediverse") # type:ignore[reportCallIssue]
|
||||
Qidian = "qidian", _("Qidian") # type:ignore[reportCallIssue]
|
||||
Ypshuo = "ypshuo", _("Ypshuo") # type:ignore[reportCallIssue]
|
||||
AO3 = "ao3", _("Archive of Our Own") # type:ignore[reportCallIssue]
|
||||
|
||||
|
||||
IdealIdTypes = [
|
||||
|
|
|
@ -38,7 +38,7 @@ from .tv.models import (
|
|||
TVShowSchema,
|
||||
)
|
||||
|
||||
from .search.models import Indexer # isort:skip
|
||||
from .search.models import Indexer, ExternalSearchResultItem # isort:skip
|
||||
|
||||
|
||||
# class Exhibition(Item):
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from ..common.sites import SiteManager
|
||||
from .ao3 import ArchiveOfOurOwn
|
||||
from .apple_music import AppleMusic
|
||||
from .bandcamp import Bandcamp
|
||||
from .bangumi import Bangumi
|
||||
|
|
64
catalog/sites/ao3.py
Normal file
64
catalog/sites/ao3.py
Normal file
|
@ -0,0 +1,64 @@
|
|||
import logging
|
||||
|
||||
from catalog.book.models import *
|
||||
from catalog.common import *
|
||||
|
||||
|
||||
@SiteManager.register
|
||||
class ArchiveOfOurOwn(AbstractSite):
|
||||
SITE_NAME = SiteName.AO3
|
||||
ID_TYPE = IdType.AO3
|
||||
URL_PATTERNS = [
|
||||
r"\w+://archiveofourown\.org/works/(\d+)",
|
||||
]
|
||||
WIKI_PROPERTY_ID = "?"
|
||||
DEFAULT_MODEL = Edition
|
||||
|
||||
@classmethod
|
||||
def id_to_url(cls, id_value):
|
||||
return "https://archiveofourown.org/works/" + id_value
|
||||
|
||||
def scrape(self):
|
||||
if not self.url:
|
||||
raise ParseError(self, "url")
|
||||
content = BasicDownloader(self.url + "?view_adult=true").download().html()
|
||||
|
||||
title = content.xpath("string(//h2[@class='title heading'])")
|
||||
if not title:
|
||||
raise ParseError(self, "title")
|
||||
authors = content.xpath("//h3[@class='byline heading']/a/text()")
|
||||
summary = content.xpath(
|
||||
"string(//div[@class='summary module']//blockquote[@class='userstuff'])"
|
||||
)
|
||||
language = [
|
||||
s.strip()
|
||||
for s in content.xpath("//dd[@class='language']/text()") # type:ignore
|
||||
]
|
||||
|
||||
published = content.xpath("string(//dd[@class='published']/text())")
|
||||
if published:
|
||||
pub_date = published.split("-") # type:ignore
|
||||
pub_year = int(pub_date[0])
|
||||
pub_month = int(pub_date[1])
|
||||
else:
|
||||
pub_year = None
|
||||
pub_month = None
|
||||
data = {
|
||||
"localized_title": [{"lang": "en", "text": title.strip()}], # type:ignore
|
||||
"localized_description": (
|
||||
[
|
||||
{"lang": "en", "text": summary.strip()} # type:ignore
|
||||
]
|
||||
if summary
|
||||
else []
|
||||
),
|
||||
"author": authors,
|
||||
"language": language,
|
||||
"pub_year": pub_year,
|
||||
"pub_month": pub_month,
|
||||
"format": Edition.BookFormat.WEB,
|
||||
# "words": words,
|
||||
}
|
||||
|
||||
pd = ResourceContent(metadata=data)
|
||||
return pd
|
|
@ -18,6 +18,12 @@
|
|||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.ao3 {
|
||||
border: none;
|
||||
color: white;
|
||||
background-color: #900;
|
||||
}
|
||||
|
||||
.qidian, .ypshuo {
|
||||
border: none;
|
||||
color: white;
|
||||
|
|
|
@ -0,0 +1,600 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge" />
|
||||
<meta name="keywords" content="fanfiction, transformative works, otw, fair use, archive" />
|
||||
<meta name="language" content="en-US" />
|
||||
<meta name="subject" content="fandom" />
|
||||
<meta name="description" content="An Archive of Our Own, a project of the
|
||||
Organization for Transformative Works" />
|
||||
<meta name="distribution" content="GLOBAL" />
|
||||
<meta name="classification" content="transformative works" />
|
||||
<meta name="author" content="Organization for Transformative Works" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title>
|
||||
I Am Groot - sherlocksmyth - Multifandom [Archive of Our Own]
|
||||
</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css" media="screen" href="/stylesheets/skins/skin_1_default/1_site_screen_.css" />
|
||||
<link rel="stylesheet" type="text/css" media="only screen and (max-width: 62em), handheld" href="/stylesheets/skins/skin_1_default/4_site_midsize.handheld_.css" />
|
||||
<link rel="stylesheet" type="text/css" media="only screen and (max-width: 42em), handheld" href="/stylesheets/skins/skin_1_default/5_site_narrow.handheld_.css" />
|
||||
<link rel="stylesheet" type="text/css" media="speech" href="/stylesheets/skins/skin_1_default/6_site_speech_.css" />
|
||||
<link rel="stylesheet" type="text/css" media="print" href="/stylesheets/skins/skin_1_default/7_site_print_.css" />
|
||||
<!--[if IE 8]><link rel="stylesheet" type="text/css" media="screen" href="/stylesheets/skins/skin_1_default/8_site_screen_IE8_or_lower.css" /><![endif]-->
|
||||
<!--[if IE 5]><link rel="stylesheet" type="text/css" media="screen" href="/stylesheets/skins/skin_1_default/9_site_screen_IE5.css" /><![endif]-->
|
||||
<!--[if IE 6]><link rel="stylesheet" type="text/css" media="screen" href="/stylesheets/skins/skin_1_default/10_site_screen_IE6.css" /><![endif]-->
|
||||
<!--[if IE 7]><link rel="stylesheet" type="text/css" media="screen" href="/stylesheets/skins/skin_1_default/11_site_screen_IE7.css" /><![endif]-->
|
||||
|
||||
|
||||
<!--sandbox for developers -->
|
||||
<link rel="stylesheet" href="/stylesheets/sandbox.css" />
|
||||
|
||||
|
||||
|
||||
<script src="/javascripts/livevalidation_standalone.js"></script>
|
||||
|
||||
<meta name="csrf-param" content="authenticity_token" />
|
||||
<meta name="csrf-token" content="bna1-7_SjicFHya69xAY9xysuJp5RyLmruGPWbB4RNytTlhDhmIxqgaIJPevfVbn24KYxSmaYFNziIobCEsKhQ" />
|
||||
|
||||
|
||||
</head>
|
||||
|
||||
<body class="logged-out" >
|
||||
<div id="outer" class="wrapper">
|
||||
<ul id="skiplinks"><li><a href="#main">Main Content</a></li></ul>
|
||||
<noscript><p id="javascript-warning">While we've done our best to make the core functionality of this site accessible without JavaScript, it will work better with it enabled. Please consider turning it on!</p></noscript>
|
||||
|
||||
<!-- BEGIN header -->
|
||||
|
||||
<header id="header" class="region">
|
||||
|
||||
<h1 class="heading">
|
||||
<a href="/"><span>Archive of Our Own</span><sup> beta</sup><img alt="Archive of Our Own" class="logo" src="/images/ao3_logos/logo_42.png" /></a>
|
||||
</h1>
|
||||
|
||||
<div id="login" class="dropdown">
|
||||
<p class="user actions">
|
||||
<a id="login-dropdown" href="/users/login">Log In</a>
|
||||
</p>
|
||||
<div id="small_login" class="simple login">
|
||||
<form class="new_user" id="new_user_session_small" action="/users/login" accept-charset="UTF-8" method="post"><input type="hidden" name="authenticity_token" value="abUtVNjRPC-hP2aZZ99AMVihkcRzRJuV_o8-t2lYsA4a9YbwiIYADHJXaFsmATttxR0aJJCjceAgrwcxzYU73A" autocomplete="off" />
|
||||
<dl>
|
||||
<dt>
|
||||
<label for="user_session_login_small">User name or email:</label></dt>
|
||||
<dd><input id="user_session_login_small" type="text" name="user[login]" /></dd>
|
||||
<dt><label for="user_session_password_small">Password:</label></dt>
|
||||
<dd><input id="user_session_password_small" type="password" name="user[password]" /></dd>
|
||||
</dl>
|
||||
<p class="submit actions">
|
||||
<label for="user_remember_me_small" class="action"><input type="checkbox" name="user[remember_me]" id="user_remember_me_small" value="1" />Remember Me</label>
|
||||
<input type="submit" name="commit" value="Log In" />
|
||||
</p>
|
||||
</form>
|
||||
<ul class="footnote actions">
|
||||
<li><a href="/users/password/new">Forgot password?</a></li>
|
||||
<li>
|
||||
<a href="/invite_requests">Get an Invitation</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<nav aria-label="Site">
|
||||
<ul class="primary navigation actions">
|
||||
<li class="dropdown">
|
||||
<a href="/menu/fandoms">Fandoms</a>
|
||||
<ul class="menu">
|
||||
<li><a href="/media">All Fandoms</a></li>
|
||||
<li id="medium_5"><a href="/media/Anime%20*a*%20Manga/fandoms">Anime & Manga</a></li>
|
||||
<li id="medium_3"><a href="/media/Books%20*a*%20Literature/fandoms">Books & Literature</a></li>
|
||||
<li id="medium_4"><a href="/media/Cartoons%20*a*%20Comics%20*a*%20Graphic%20Novels/fandoms">Cartoons & Comics & Graphic Novels</a></li>
|
||||
<li id="medium_7"><a href="/media/Celebrities%20*a*%20Real%20People/fandoms">Celebrities & Real People</a></li>
|
||||
<li id="medium_2"><a href="/media/Movies/fandoms">Movies</a></li>
|
||||
<li id="medium_6"><a href="/media/Music%20*a*%20Bands/fandoms">Music & Bands</a></li>
|
||||
<li id="medium_8"><a href="/media/Other%20Media/fandoms">Other Media</a></li>
|
||||
<li id="medium_30198"><a href="/media/Theater/fandoms">Theater</a></li>
|
||||
<li id="medium_1"><a href="/media/TV%20Shows/fandoms">TV Shows</a></li>
|
||||
<li id="medium_476"><a href="/media/Video%20Games/fandoms">Video Games</a></li>
|
||||
<li id="medium_9971"><a href="/media/Uncategorized%20Fandoms/fandoms">Uncategorized Fandoms</a></li>
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="/menu/browse">Browse</a>
|
||||
<ul class="menu">
|
||||
<li><a href="/works">Works</a></li>
|
||||
<li><a href="/bookmarks">Bookmarks</a></li>
|
||||
<li><a href="/tags">Tags</a></li>
|
||||
<li><a href="/collections">Collections</a></li>
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="/menu/search">Search</a>
|
||||
<ul class="menu">
|
||||
<li><a href="/works/search">Works</a></li>
|
||||
<li><a href="/bookmarks/search">Bookmarks</a></li>
|
||||
<li><a href="/tags/search">Tags</a></li>
|
||||
<li><a href="/people/search">People</a></li>
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="/menu/about">About</a>
|
||||
<ul class="menu">
|
||||
<li><a href="/about">About Us</a></li>
|
||||
<li><a href="/admin_posts">News</a></li>
|
||||
<li><a href="/faq">FAQ</a></li>
|
||||
<li><a href="/wrangling_guidelines">Wrangling Guidelines</a></li>
|
||||
<li><a href="/donate">Donate or Volunteer</a></li>
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
<li class="search"><form class="search" id="search" role="search" aria-label="Work" action="/works/search" accept-charset="UTF-8" method="get">
|
||||
<fieldset>
|
||||
<p>
|
||||
<label class="landmark" for="site_search">Work Search</label>
|
||||
<input class="text" id="site_search" aria-describedby="site_search_tooltip" type="text" name="work_search[query]" />
|
||||
<span class="tip" role="tooltip" id="site_search_tooltip">tip: arthur merlin words>1000 sort:hits</span>
|
||||
<span class="submit actions"><input type="submit" value="Search" class="button" /></span>
|
||||
</p>
|
||||
</fieldset>
|
||||
</form></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
|
||||
|
||||
<div class="clear"></div>
|
||||
|
||||
</header>
|
||||
|
||||
|
||||
|
||||
<!-- END header -->
|
||||
|
||||
<div id="inner" class="wrapper">
|
||||
<!-- BEGIN sidebar -->
|
||||
<!-- END sidebar -->
|
||||
|
||||
<!-- BEGIN main -->
|
||||
<div id="main" class="works-show region" role="main">
|
||||
|
||||
<div class="flash"></div>
|
||||
<!--page description, messages-->
|
||||
<ul class="landmark skip">
|
||||
<li><a name="top"> </a></li>
|
||||
<li><a href="#work">Skip header</a></li>
|
||||
</ul>
|
||||
|
||||
<!--/descriptions-->
|
||||
|
||||
<!--subnav-->
|
||||
<!--/subnav-->
|
||||
|
||||
<!-- BEGIN revealed -->
|
||||
<!-- BEGIN work -->
|
||||
<!--work description, metadata, notes and messages-->
|
||||
<!-- BEGIN navigation -->
|
||||
<h3 class="landmark heading">Actions</h3>
|
||||
<ul class="work navigation actions" role="menu">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="comments" id="show_comments_link_top">
|
||||
<a data-remote="true" href="/comments/show_comments?work_id=2080878">Comments </a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
<li class="share hidden">
|
||||
<a class=" modal" title="Share Work" href="/works/2080878/share">Share</a>
|
||||
</li>
|
||||
|
||||
|
||||
<li class="download" aria-haspopup="true">
|
||||
<a href="#">Download</a>
|
||||
<ul class="expandable secondary">
|
||||
<li><a href="/downloads/2080878/I_Am_Groot.azw3?updated_at=1722263242">AZW3</a></li>
|
||||
<li><a href="/downloads/2080878/I_Am_Groot.epub?updated_at=1722263242">EPUB</a></li>
|
||||
<li><a href="/downloads/2080878/I_Am_Groot.mobi?updated_at=1722263242">MOBI</a></li>
|
||||
<li><a href="/downloads/2080878/I_Am_Groot.pdf?updated_at=1722263242">PDF</a></li>
|
||||
<li><a href="/downloads/2080878/I_Am_Groot.html?updated_at=1722263242">HTML</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- END navigation -->
|
||||
|
||||
|
||||
<h3 class="landmark heading">Work Header</h3>
|
||||
|
||||
<div class="wrapper">
|
||||
|
||||
<dl class="work meta group">
|
||||
<dt class="rating tags">
|
||||
|
||||
Rating:
|
||||
</dt>
|
||||
|
||||
<dd class="rating tags">
|
||||
<ul class="commas">
|
||||
<li><a class="tag" href="/tags/Explicit/works">Explicit</a></li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dt class="warning tags">
|
||||
|
||||
<a href="/tos_faq#tags">Archive Warning</a>:
|
||||
</dt>
|
||||
|
||||
<dd class="warning tags">
|
||||
<ul class="commas">
|
||||
<li><a class="tag" href="/tags/Choose%20Not%20To%20Use%20Archive%20Warnings/works">Creator Chose Not To Use Archive Warnings</a></li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dt class="fandom tags">
|
||||
|
||||
Fandoms:
|
||||
</dt>
|
||||
|
||||
<dd class="fandom tags">
|
||||
<ul class="commas">
|
||||
<li><a class="tag" href="/tags/Guardians%20of%20the%20Galaxy%20-%20All%20Media%20Types/works">Guardians of the Galaxy - All Media Types</a></li><li><a class="tag" href="/tags/Marvel/works">Marvel</a></li><li><a class="tag" href="/tags/Marvel%20(Movies)/works">Marvel (Movies)</a></li><li><a class="tag" href="/tags/Marvel%20(Comics)/works">Marvel (Comics)</a></li><li><a class="tag" href="/tags/Guardians%20of%20the%20Galaxy%20(Comics)/works">Guardians of the Galaxy (Comics)</a></li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dt class="character tags">
|
||||
|
||||
Character:
|
||||
</dt>
|
||||
|
||||
<dd class="character tags">
|
||||
<ul class="commas">
|
||||
<li><a class="tag" href="/tags/Groot%20(Marvel)/works">Groot (Marvel)</a></li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dt class="freeform tags">
|
||||
|
||||
Additional Tags:
|
||||
</dt>
|
||||
|
||||
<dd class="freeform tags">
|
||||
<ul class="commas">
|
||||
<li><a class="tag" href="/tags/NSFW/works">NSFW</a></li>
|
||||
</ul>
|
||||
</dd>
|
||||
|
||||
<dt class="language">
|
||||
Language:
|
||||
</dt>
|
||||
<dd class="language" lang="en">
|
||||
English
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
<dt class="stats">Stats:</dt>
|
||||
<dd class="stats">
|
||||
<!-- end of cache -->
|
||||
|
||||
<dl class="stats"><dt class="published">Published:</dt><dd class="published">2014-08-04</dd><dt class="words">Words:</dt><dd class="words">1,308</dd><dt class="chapters">Chapters:</dt><dd class="chapters">1/1</dd><dt class="comments">Comments:</dt><dd class="comments">4,969</dd><dt class="kudos">Kudos:</dt><dd class="kudos">156,230</dd><dt class="bookmarks">Bookmarks:</dt><dd class="bookmarks"><a href="/works/2080878/bookmarks">6,177</a></dd><dt class="hits">Hits:</dt><dd class="hits">1,167,642</dd></dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<!-- BEGIN section where work skin applies -->
|
||||
<div id="workskin">
|
||||
<div class="preface group">
|
||||
<h2 class="title heading">
|
||||
I Am Groot
|
||||
</h2>
|
||||
<h3 class="byline heading">
|
||||
<a rel="author" href="/users/sherlocksmyth/pseuds/sherlocksmyth">sherlocksmyth</a>
|
||||
</h3>
|
||||
|
||||
|
||||
<div class="summary module">
|
||||
<h3 class="heading">Summary:</h3>
|
||||
<blockquote class="userstuff">
|
||||
<p>EXTREMELY NSFW fic told from the perspective of Groot.</p><p>EDIT 04/05/2021:<br />Wow. I just found out this is the top fic on AO3. I’m losing my mind. Thank you guys for the kudos & views! If you want you can follow me on TikTok (@supercolm), Twitter (@super_colm) and Twitch! twitch.tv/ColmTheeGamer</p>
|
||||
</blockquote>
|
||||
</div>
|
||||
|
||||
<div class="notes module">
|
||||
<h3 class="heading">Notes:</h3>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<blockquote class="userstuff">
|
||||
<p>Had to take a break halfway through writing this fic because the raw emotion overpowered me.</p>
|
||||
</blockquote>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<!--/descriptions-->
|
||||
|
||||
<!--chapter content-->
|
||||
<div id="chapters" role="article">
|
||||
<h3 class="landmark heading" id="work">Work Text:</h3>
|
||||
<div class="userstuff">ACTUAL CONTENT REMOVED</div>
|
||||
<!-- end cache -->
|
||||
</div>
|
||||
<!--/chapter-->
|
||||
|
||||
|
||||
</div>
|
||||
<!-- END work skin -->
|
||||
<!-- END work -->
|
||||
|
||||
<!-- BEGIN comment section -->
|
||||
<!-- Gets embedded anywhere we need to list comments on a top-level commentable. We need the local variable "commentable" here. -->
|
||||
<div id="feedback" class="feedback">
|
||||
|
||||
<h3 class="landmark heading">Actions</h3>
|
||||
|
||||
<ul class="actions" role="navigation">
|
||||
<li><a href="#main">↑ Top</a></li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li>
|
||||
<form id="new_kudo" action="/kudos" accept-charset="UTF-8" method="post"><input type="hidden" name="authenticity_token" value="OpfV0aNDU2_ieQ30EoMYNEsifiZkEr1OSrvpuFRKdUmOuQb6FDpM8Lb9mjeyrvL3_kvzTLM9vRKjx5IX_8csZw" autocomplete="off" />
|
||||
<input value="2080878" autocomplete="off" type="hidden" name="kudo[commentable_id]" id="kudo_commentable_id" />
|
||||
<input value="Work" autocomplete="off" type="hidden" name="kudo[commentable_type]" id="kudo_commentable_type" />
|
||||
<input type="submit" name="commit" value="Kudos ♥" id="kudo_submit" />
|
||||
</form> </li>
|
||||
|
||||
|
||||
|
||||
|
||||
<li id="show_comments_link"><a data-remote="true" href="/comments/show_comments?work_id=2080878">Comments (4969)</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<div id="kudos_message"></div>
|
||||
|
||||
|
||||
<h3 class="landmark heading">Kudos</h3>
|
||||
<div id="kudos">
|
||||
<p class="kudos">
|
||||
<a href="/users/Chelik">Chelik</a>, <a href="/users/BobTheLobster">BobTheLobster</a>, <a href="/users/Lowe_is_cool">Lowe_is_cool</a>, <a href="/users/amajortragedy">amajortragedy</a>, <a href="/users/ughhdotpng">ughhdotpng</a>, <a href="/users/Icantbelievewerenotalldeadyet">Icantbelievewerenotalldeadyet</a>, <a href="/users/Ayelen">Ayelen</a>, <a href="/users/joeidkman">joeidkman</a>, <a href="/users/Lycone">Lycone</a>, <a href="/users/Scarlettdragon27">Scarlettdragon27</a>, <a href="/users/Jassiemil">Jassiemil</a>, <a href="/users/MarLeb">MarLeb</a>, <a href="/users/Lizepubhorder">Lizepubhorder</a>, <a href="/users/Hedwig649">Hedwig649</a>, <a href="/users/FloweringCat">FloweringCat</a>, <a href="/users/XerexisSar">XerexisSar</a>, <a href="/users/bernadineisreborn">bernadineisreborn</a>, <a href="/users/candlecrow">candlecrow</a>, <a href="/users/Amuleto">Amuleto</a>, <a href="/users/sanctimonia">sanctimonia</a>, <a href="/users/WordsmithDee">WordsmithDee</a>, <a href="/users/Sludgelord">Sludgelord</a>, <a href="/users/irishbeings">irishbeings</a>, <a href="/users/Mintze">Mintze</a>, <a href="/users/FulGurkan">FulGurkan</a>, <a href="/users/Athyna">Athyna</a>, <a href="/users/JenCollins">JenCollins</a>, <a href="/users/Yayah414">Yayah414</a>, <a href="/users/onacloudedmistynight">onacloudedmistynight</a>, <a href="/users/Angels_dust">Angels_dust</a>, <a href="/users/Didianita">Didianita</a>, <a href="/users/demonicfaerie2009">demonicfaerie2009</a>, <a href="/users/kradihsoy">kradihsoy</a>, <a href="/users/Pomelo_sacredwater">Pomelo_sacredwater</a>, <a href="/users/pickledRatchet">pickledRatchet</a>, <a href="/users/Alisexoxo">Alisexoxo</a>, <a href="/users/NopeZone">NopeZone</a>, <a href="/users/BlueberryMoons">BlueberryMoons</a>, <a href="/users/LadyJay15">LadyJay15</a>, <a href="/users/Clxarke">Clxarke</a>, <a href="/users/Mad_mags_patuti">Mad_mags_patuti</a>, <a href="/users/wolfxe">wolfxe</a>, <a href="/users/Depressed_Ghost5">Depressed_Ghost5</a>, <a href="/users/Gavilan">Gavilan</a>, <a href="/users/beebo_beebo">beebo_beebo</a>, <a href="/users/beyoursledgehammer">beyoursledgehammer</a>, <a href="/users/Mojioji">Mojioji</a>, <a href="/users/sucksfierro">sucksfierro</a>, <a href="/users/Lynnie_7">Lynnie_7</a>, <a href="/users/archiveofadreamer">archiveofadreamer</a><span id="kudos_more_connector">, and </span><a id="kudos_more_link" data-remote="true" href="/works/2080878/kudos?before=6839325232">77693 more users</a>
|
||||
as well as
|
||||
78487 guests
|
||||
left kudos on this work!
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<h3 class="landmark heading"><a id="comments">Comments</a></h3>
|
||||
|
||||
|
||||
<div id="add_comment_placeholder" title="top level comment">
|
||||
<div id="add_comment">
|
||||
<!-- expects the local variables comment, commentable, and button_name -->
|
||||
<div class="post comment" id="comment_form_for_2080878">
|
||||
<form class="new_comment" id="comment_for_2080878" action="/works/2080878/comments" accept-charset="UTF-8" method="post"><input type="hidden" name="authenticity_token" value="n-WIiJyc1Ln74gD623DaA6txuRI61ZhcQPuwwdkAhACaI-AxxIbY70sPvXVVDx9Ip37AFqI2LS8lxd5L4neSLg" autocomplete="off" />
|
||||
<fieldset>
|
||||
<legend>Post Comment</legend>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl>
|
||||
<dt class="landmark">Note:</dt>
|
||||
<dd class="instructions comment_form">All fields are required. Your email address will not be published.</dd>
|
||||
<dt><label for="comment_name_for_2080878">Guest name</label></dt>
|
||||
<dd>
|
||||
<input id="comment_name_for_2080878" type="text" name="comment[name]" />
|
||||
<script>
|
||||
//<![CDATA[
|
||||
var validation_for_comment_name_for_2080878 = new LiveValidation('comment_name_for_2080878', { wait: 500, onlyOnBlur: false });
|
||||
validation_for_comment_name_for_2080878.add(Validate.Presence, {"failureMessage":"Please enter your name.","validMessage":""});
|
||||
//]]>
|
||||
</script>
|
||||
</dd>
|
||||
<dt><label for="comment_email_for_2080878">Guest email</label></dt>
|
||||
<dd>
|
||||
<input id="comment_email_for_2080878" type="text" name="comment[email]" />
|
||||
<script>
|
||||
//<![CDATA[
|
||||
var validation_for_comment_email_for_2080878 = new LiveValidation('comment_email_for_2080878', { wait: 500, onlyOnBlur: false });
|
||||
validation_for_comment_email_for_2080878.add(Validate.Presence, {"failureMessage":"Please enter your email address.","validMessage":""});
|
||||
//]]>
|
||||
</script>
|
||||
</dd>
|
||||
</dl>
|
||||
<p class="footnote">(Plain text with limited HTML <a class="help symbol question modal" title="Html help" href="/help/html-help.html"><span class="symbol question"><span>?</span></span></a>)</p>
|
||||
|
||||
<p>
|
||||
<label for="comment_content_for_2080878" class="landmark">Comment</label>
|
||||
<textarea id="comment_content_for_2080878" class="comment_form observe_textlength" title="Enter Comment" name="comment[comment_content]">
|
||||
</textarea>
|
||||
<input type="hidden" id="controller_name_for_2080878" name="controller_name" value="works" />
|
||||
</p>
|
||||
<p class="character_counter" tabindex="0"><span id="comment_content_for_2080878_counter" class="value" data-maxlength="10000">10000</span> characters left</p>
|
||||
<script>
|
||||
//<![CDATA[
|
||||
var validation_for_comment_content_for_2080878 = new LiveValidation('comment_content_for_2080878', { wait: 500, onlyOnBlur: false });
|
||||
validation_for_comment_content_for_2080878.add(Validate.Presence, {"failureMessage":"Brevity is the soul of wit, but we need your comment to have text in it.","validMessage":""});
|
||||
validation_for_comment_content_for_2080878.add(Validate.Length, {"maximum":"10000","tooLongMessage":"must be less than 10000 characters long."});
|
||||
//]]>
|
||||
</script>
|
||||
<p class="submit actions">
|
||||
<input type="submit" name="commit" value="Comment" id="comment_submit_for_2080878" data-disable-with="Please wait..." />
|
||||
</p>
|
||||
</fieldset>
|
||||
</form></div>
|
||||
<div class="clear"></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- If we have javascript, here is where the comments will be spiffily inserted -->
|
||||
<!-- If not, and show_comments is true, here is where the comments will be rendered -->
|
||||
<div id="comments_placeholder" style="display:none;">
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<!-- END comments -->
|
||||
|
||||
<!-- END comment section -->
|
||||
<!-- END revealed -->
|
||||
|
||||
|
||||
|
||||
<div class="clear"><!--presentational--></div>
|
||||
</div>
|
||||
<!-- END main -->
|
||||
</div>
|
||||
<!-- BEGIN footer -->
|
||||
<div id="footer" role="contentinfo" class="region">
|
||||
<h3 class="landmark heading">Footer</h3>
|
||||
<ul class="navigation actions" role="navigation">
|
||||
<li class="module group">
|
||||
<h4 class="heading">About the Archive</h4>
|
||||
<ul class="menu">
|
||||
<li><a href="/site_map">Site Map</a></li>
|
||||
<li><a href="/diversity">Diversity Statement</a></li>
|
||||
<li><a href="/tos">Terms of Service</a></li>
|
||||
<li><a href="/content">Content Policy</a></li>
|
||||
<li><a href="/privacy">Privacy Policy</a></li>
|
||||
<li><a href="/dmca">DMCA Policy</a> </li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="module group">
|
||||
<h4 class="heading">Contact Us</h4>
|
||||
<ul class="menu">
|
||||
<li><a href="/abuse_reports/new">Policy Questions & Abuse Reports</a></li>
|
||||
<li><a href="/support">Technical Support & Feedback</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="module group">
|
||||
<h4 class="heading">Development</h4>
|
||||
<ul class="menu">
|
||||
<li>
|
||||
<a href="https://github.com/otwcode/otwarchive/commits/v0.9.384.9">otwarchive v0.9.384.9</a>
|
||||
</li>
|
||||
<li><a href="/known_issues">Known Issues</a></li>
|
||||
<li>
|
||||
<a title="View License" href="https://www.gnu.org/licenses/old-licenses/gpl-2.0.html">GPL-2.0-or-later</a> by the <a title="Organization for Transformative Works" href="https://transformativeworks.org/">OTW</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- END footer -->
|
||||
|
||||
</div>
|
||||
<!-- check to see if this controller/action allow tinymce before we load the gigantor js; see application_helper -->
|
||||
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js" type="text/javascript"></script>
|
||||
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.0/jquery-ui.min.js" type="text/javascript"></script>
|
||||
<!-- if user has googleapis blocked for some reason we need a fallback -->
|
||||
<script type="text/javascript">
|
||||
if (typeof jQuery == 'undefined') {
|
||||
document.write(unescape("%3Cscript src='/javascripts/jquery.min.js' type='text/javascript'%3E%3C/script%3E"));
|
||||
document.write(unescape("%3Cscript src='/javascripts/jquery-ui.min.js' type='text/javascript'%3E%3C/script%3E"));
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/javascript">$j = jQuery.noConflict();</script>
|
||||
<script src="/javascripts/jquery.scrollTo.min.js"></script>
|
||||
<script src="/javascripts/jquery.livequery.min.js"></script>
|
||||
<script src="/javascripts/rails.js"></script>
|
||||
<script src="/javascripts/application.js"></script>
|
||||
<script src="/javascripts/bootstrap/bootstrap-dropdown.min.js"></script>
|
||||
<script src="/javascripts/jquery-shuffle.js"></script>
|
||||
<script src="/javascripts/jquery.tokeninput.min.js"></script>
|
||||
<script src="/javascripts/jquery.trap.min.js"></script>
|
||||
<script src="/javascripts/ao3modal.min.js"></script>
|
||||
<script src="/javascripts/js.cookie.min.js"></script>
|
||||
|
||||
<script src="/javascripts/filters.min.js"></script>
|
||||
|
||||
|
||||
<script>
|
||||
//<![CDATA[
|
||||
|
||||
// We can't rely on !window.localStorage to test localStorage support in
|
||||
// browsers like Safari 9, which technically support it, but which have a
|
||||
// storage length of 0 in private mode.
|
||||
// Credit: https://github.com/getgrav/grav-plugin-admin/commit/cfe2188f10c4ca604e03c96f3e21537fda1cdf9a
|
||||
function isSupported() {
|
||||
var item = "localStoragePolyfill";
|
||||
try {
|
||||
localStorage.setItem(item, item);
|
||||
localStorage.removeItem(item);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function acceptTOS() {
|
||||
if (isSupported()) {
|
||||
localStorage.setItem("accepted_tos", "20241119");
|
||||
} else {
|
||||
Cookies.set("accepted_tos", "20241119", { expires: 365 });
|
||||
}
|
||||
}
|
||||
|
||||
$j(document).ready(function() {
|
||||
if (localStorage.getItem("accepted_tos") !== "20241119" && Cookies.get("accepted_tos") !== "20241119") {
|
||||
$j("body").prepend("<div id=\"tos_prompt\" class=\"hidden\">\n <h2 class=\"heading\">\n <span>Archive of Our Own<\/span>\n <\/h2>\n <div class=\"agreement\">\n <p>\n On the Archive of Our Own (AO3), users can create works, bookmarks, comments, tags, and other <a href=\"/tos_faq#define_content\">Content<\/a>. Any information you publish on AO3 may be accessible by the public, AO3 users, and/or AO3 personnel. Be mindful when sharing personal information, including but not limited to your name, email, age, location, personal relationships, gender or sexual identity, racial or ethnic background, religious or political views, and/or account usernames for other sites.\n <\/p>\n <p>\n To learn more, check out our <a href=\"/tos\">Terms of Service<\/a>, including the <a href=\"/content\">Content Policy<\/a> and <a href=\"/privacy\">Privacy Policy<\/a>.\n <\/p>\n\n <p class=\"confirmation\">\n <input type=\"checkbox\" id=\"tos_agree\" />\n <label for=\"tos_agree\">I have read & understood the 2024 Terms of Service, including the Content Policy and Privacy Policy.<\/label>\n <\/p>\n\n <p class=\"confirmation\">\n <input type=\"checkbox\" id=\"data_processing_agree\" />\n <label for=\"data_processing_agree\">By checking this box, you consent to the processing of your personal data in the United States and other jurisdictions in connection with our provision of AO3 and its related services to you. You acknowledge that the data privacy laws of such jurisdictions may differ from those provided in your jurisdiction. For more information about how your personal data will be processed, please refer to our Privacy Policy.<\/label>\n <\/p>\n\n <p class=\"submit\">\n <button name=\"button\" type=\"button\" disabled=\"disabled\" id=\"accept_tos\">I agree/consent to these Terms<\/button>\n <\/p>\n\n <\/div>\n<\/div>\n\n<script>\n//<![CDATA[\n\n \$j(document).ready(function() {\n var container = \$j(\"#tos_prompt\");\n var outer = \$j(\"#outer\");\n var button = \$j(\"#accept_tos\");\n var tosCheckbox = document.getElementById(\"tos_agree\");\n var dataProcessingCheckbox = document.getElementById(\"data_processing_agree\");\n\n var checkboxClicked = function() {\n button.attr(\"disabled\", !tosCheckbox.checked || !dataProcessingCheckbox.checked);\n if (this.checked) {\n button.on(\"click\", function() {\n acceptTOS();\n outer.removeClass(\"hidden\").removeAttr(\"aria-hidden\");\n \$j.when(container.fadeOut(500)).done(function() {\n container.remove();\n });\n });\n };\n };\n\n setTimeout(showTOSPrompt, 1500);\n\n function showTOSPrompt() {\n \$j.when(container.fadeIn(500)).done(function() {\n outer.addClass(\"hidden\").attr(\"aria-hidden\", \"true\");\n });\n\n \$j(\"#tos_agree\").on(\"click\", checkboxClicked).change();\n \$j(\"#data_processing_agree\").on(\"click\", checkboxClicked).change();\n };\n });\n\n//]]]]><![CDATA[>\n<\/script>");
|
||||
}
|
||||
});
|
||||
|
||||
//]]>
|
||||
</script>
|
||||
<script>
|
||||
//<![CDATA[
|
||||
|
||||
$j(document).ready(function() {
|
||||
var permitted_hosts = ["104.153.64.122","208.85.241.152","208.85.241.157","ao3.org","archiveofourown.com","archiveofourown.gay","archiveofourown.net","archiveofourown.org","download.archiveofourown.org","insecure.archiveofourown.org","secure.archiveofourown.org","www.archiveofourown.com","www.archiveofourown.net","www.archiveofourown.org","www.ao3.org","archive.transformativeworks.org"];
|
||||
var current_host = window.location.hostname;
|
||||
|
||||
if (!permitted_hosts.includes(current_host) && Cookies.get("proxy_notice") !== "0" && window.location.protocol !== "file:") {
|
||||
$j("#skiplinks").after("<div id=\"proxy-notice\">\n <div class=\"userstuff\">\n <p class=\"important\">Important message:<\/p>\n <ol>\n <li>You are using a proxy site that is not part of the Archive of Our Own.<\/li>\n <li>The entity that set up the proxy site can see what you submit, including your IP address. If you log in through the proxy site, it can see your password.<\/li>\n <\/ol>\n <p class=\"important\">重要提示:<\/p>\n <ol>\n <li>您使用的是第三方开发的反向代理网站,此网站并非Archive of Our Own - AO3(AO3作品库)原站。<\/li>\n <li>代理网站的开发者能够获取您上传至该站点的全部内容,包括您的ip地址。如您通过代理登录AO3,对方将获得您的密码。<\/li>\n <\/ol>\n <p class=\"submit\"><button class=\"action\" type=\"button\" id=\"proxy-notice-dismiss\">Dismiss Notice<\/button><\/p>\n <\/div>\n<\/div>\n\n<script>\n//<![CDATA[\n\n \$j(document).ready(function() {\n \$j(\"#proxy-notice-dismiss\").on(\"click\", function() {\n Cookies.set(\"proxy_notice\", \"0\");\n \$j(\"#proxy-notice\").slideUp();\n });\n });\n\n//]]]]><![CDATA[>\n<\/script>");
|
||||
}
|
||||
});
|
||||
|
||||
//]]>
|
||||
</script>
|
||||
<script>
|
||||
$j(document).on("loadedCSRF", function() {
|
||||
function send() {
|
||||
$j.post("/works/2080878/hit_count.json")
|
||||
}
|
||||
|
||||
// If a browser doesn't support prerendering, then document.prerendering
|
||||
// will be undefined, and we'll just send the hit count immediately.
|
||||
if (document.prerendering) {
|
||||
document.addEventListener("prerenderingchange", send);
|
||||
} else {
|
||||
send();
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
<script>(function(){function c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'8eeef960e829e765',t:'MTczMzY4NDE3My4wMDAwMDA='};var a=document.createElement('script');a.nonce='';a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script></body>
|
||||
</html>
|
Loading…
Add table
Reference in a new issue