diff --git a/database/Creators/913304C0CC74CC1F/74CC1F_0D3AA40F2B3A0_000.ppm b/database/Creators/913304C0CC74CC1F/74CC1F_0D3AA40F2B3A0_000.ppm new file mode 100644 index 0000000..df5680a Binary files /dev/null and b/database/Creators/913304C0CC74CC1F/74CC1F_0D3AA40F2B3A0_000.ppm differ diff --git a/database/Creators/913304C0CC74CC1F/flipnotes.dat b/database/Creators/913304C0CC74CC1F/flipnotes.dat new file mode 100644 index 0000000..4eeff11 --- /dev/null +++ b/database/Creators/913304C0CC74CC1F/flipnotes.dat @@ -0,0 +1 @@ +74CC1F_0D3AA40F2B3A0_000 2 0 0 0 0 0 0 \ No newline at end of file diff --git a/database/__init__.py b/database/__init__.py new file mode 100644 index 0000000..d223990 --- /dev/null +++ b/database/__init__.py @@ -0,0 +1,161 @@ +from __future__ import annotations + +import atexit +import os + +try: + from twisted.internet import reactor +except ImportError: # Allows the database module to be used/tested without Twisted installed. + reactor = None + +from Hatenatools import TMB + + +class Database: + """Plain-text Flipnote database used by the original server. + + This backend is intentionally single-process, matching the original design. + """ + + def __init__(self): + newest_path = "database/new_flipnotes.dat" + if os.path.exists(newest_path): + with open(newest_path, "r", encoding="utf-8", newline="") as f: + raw = f.read() + else: + raw = "" + + self.Newest = [tuple(line.split("\t")) for line in raw.splitlines() if line] if raw else [] + self.Creator = {} + + self.new = False + self.Views = 0 + self.Stars = 0 + self.Downloads = 0 + + if reactor is not None: + reactor.callLater(60 * 3, self.flusher) + atexit.register(self.write) + + def flusher(self): + if reactor is not None: + reactor.callLater(60 * 3, self.flusher) + self.write() + + def write(self): + if self.new: + if len(self.Newest) > 5000: + self.Newest = self.Newest[:5000] + with open("database/new_flipnotes.dat", "w", encoding="utf-8", newline="") as f: + f.write("\n".join("\t".join(map(str, row)) for row in self.Newest)) + self.new = False + + for creator_id in list(self.Creator.keys()): + creator_dir = os.path.join("database", "Creators", creator_id) + os.makedirs(creator_dir, exist_ok=True) + with open(os.path.join(creator_dir, "flipnotes.dat"), "w", encoding="utf-8", newline="") as f: + f.write("\n".join("\t".join(map(str, row)) for row in self.Creator[creator_id])) + del self.Creator[creator_id] + + def CreatorExists(self, CreatorID): + return os.path.exists(os.path.join("database", "Creators", CreatorID)) or CreatorID in self.Creator + + def FlipnoteExists(self, CreatorID, filename): + return os.path.exists(self.FlipnotePath(CreatorID, filename)) + + def GetCreator(self, CreatorID, Store=False): + if CreatorID in self.Creator: + return self.Creator[CreatorID] + + creator_dir = os.path.join("database", "Creators", CreatorID) + if not os.path.exists(creator_dir): + return None + + with open(os.path.join(creator_dir, "flipnotes.dat"), "r", encoding="utf-8", newline="") as f: + raw = f.read() + ret = [line.split("\t") for line in raw.splitlines() if line] + + # Current format: + # filename, views, stars, green, red, blue, purple, channel, downloads + for row in ret: + filename = row[0] + defaults = (filename, 0, 0, 0, 0, 0, 0, "", 0) + while len(row) < len(defaults): + row.append(defaults[len(row)]) + + if Store: + self.Creator[CreatorID] = ret + return ret + + def GetFlipnote(self, CreatorID, filename, Store=False): + for row in self.GetCreator(CreatorID, Store) or []: + if row[0] == filename: + return row + return False + + def GetFlipnotePPM(self, CreatorID, filename): + with open(self.FlipnotePath(CreatorID, filename), "rb") as f: + return f.read() + + def GetFlipnoteTMB(self, CreatorID, filename): + with open(self.FlipnotePath(CreatorID, filename), "rb") as f: + return f.read(0x6A0) + + def AddFlipnote(self, content, Channel=""): + content = bytes(content) + tmb = TMB().Read(content) + if not tmb: + return False + + CreatorID = tmb.EditorAuthorID + filename = tmb.CurrentFilename[:-4] + if self.FlipnoteExists(CreatorID, filename): + return False + + self.new = True + self.Newest.insert(0, (CreatorID, filename)) + + if not self.GetCreator(CreatorID, True): + self.Creator[CreatorID] = [[filename, 0, 0, 0, 0, 0, 0, Channel, 0]] + else: + self.Creator[CreatorID].append([filename, 0, 0, 0, 0, 0, 0, Channel, 0]) + + creator_dir = os.path.join("database", "Creators", CreatorID) + os.makedirs(creator_dir, exist_ok=True) + with open(self.FlipnotePath(CreatorID, filename), "wb") as f: + f.write(content) + return CreatorID, filename + + def AddView(self, CreatorID, filename): + for i, flipnote in enumerate(self.GetCreator(CreatorID, True) or []): + if flipnote[0] == filename: + self.Creator[CreatorID][i][1] = int(flipnote[1]) + 1 + self.Views += 1 + return True + return False + + def AddStar(self, CreatorID, filename, amount=1, color="yellow"): + starindices = {"yellow": 2, "green": 3, "red": 4, "blue": 5, "purple": 6} + if color not in starindices: + return False + for i, flipnote in enumerate(self.GetCreator(CreatorID, True) or []): + if flipnote[0] == filename: + idx = starindices[color] + self.Creator[CreatorID][i][idx] = int(flipnote[idx]) + amount + self.Stars += 1 + return True + return False + + def AddDownload(self, CreatorID, filename): + for i, flipnote in enumerate(self.GetCreator(CreatorID, True) or []): + if flipnote[0] == filename: + self.Creator[CreatorID][i][8] = int(flipnote[8]) + 1 + self.Downloads += 1 + return True + return False + + def FlipnotePath(self, CreatorID, filename): + return os.path.join("database", "Creators", CreatorID, filename + ".ppm") + + +Database = Database() diff --git a/database/new_flipnotes.dat b/database/new_flipnotes.dat new file mode 100644 index 0000000..20df4ab --- /dev/null +++ b/database/new_flipnotes.dat @@ -0,0 +1 @@ +913304C0CC74CC1F 74CC1F_0D3AA40F2B3A0_000 \ No newline at end of file diff --git a/hatenadir/css/ds/basic.css b/hatenadir/css/ds/basic.css new file mode 100644 index 0000000..d24c935 --- /dev/null +++ b/hatenadir/css/ds/basic.css @@ -0,0 +1,830 @@ +@charset "UTF-8"; +table.profbox { + background-color: #82c300; + color: #ffffff; +} +div.prof_out { + margin: 0 11px 0 11px; + background-color: #82c300; + border-style: solid; + border-width: 0 1px 0 1px; + border-color: #82c300; +} +span.more-f{ + color: #ffffff; +} +div.notice2 { + margin:0 11px 5px 11px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#82c300; + background-color:#fbfbfb; +} +span.url{ + text-decoration:underline; +} +span.comptxt { + color:#ff8a00; +} +span.star0 { + color:#fdc556; +} +span.star1 { + color:#138200; +} +span.star2 { + color:#ff455c; +} +span.star3 { + color:#00b0f9; +} +span.star4 { + color:#a411b9; +} +span.star0c { + color:#fdc556; +} +span.star1c { + color:#138200; +} +span.star2c { + color:#ff455c; +} +span.star3c { + color:#00b0f9; +} +span.star4c { + color:#a411b9; +} +span.orange{ + color: #ff8d45; +} +span.green { + color: #82c300; +} +span.gray{ + color: #666666; +} +span.white { + color:#FFFFFF; +} +html { + margin:0; + padding:0; +} +body { + color:#333333; + margin:0; + padding:0; +} +div.title { + margin:0 7px 0 7px; + padding:7px 5px 7px 5px; + border-style:solid; + border-width:0 0 1px 0; + border-color:#CCCCCC; +} +div.description { + margin:0 7px 0 7px; + padding:7px 5px 7px 5px; + border-style:solid; + border-width:0 0 1px 0; + border-color:#CCCCCC; +} +div.hr { + border-style:solid; + border-width:0 0 1px 0; + border-color:#CCCCCC; +} +div.hr-tab { + border-style:solid; + border-width:0 0 1px 0; + border-color:#82c300; +} +span.timestamp { + color:#999999; +} +a.timestamp { + color:#999999; +} +a.violation { + color:#333333; +} +div.box { + padding:7px; + border-style:solid; + border-width:1px; + border-color:#CCCCCC; + background-color:#FFFFFF; +} +div.more { + margin:7px 0 0 0; +} +div.pager { + padding:5px; +} +div.num { + margin:5px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#CCCCCC; + background-color:#FFFFFF; +} +span.new { + color: #cc0000; +} +span.price { + color: #92cb22; +} +span.date { + color: #cccccc; +} +table.detail{ + margin:0 7px 0 7px; +} +table.fullsize { + margin:0; +} +div.item-term { + padding:3px 0 3px 5px; +} +div.item-value { + padding:3px 5px 3px 0; +} +div.item-text { + padding:3px 5px 3px 15px; +} +div.item-tcom { + padding: 3px 5px 0 5px; +} +div.item-com { + padding: 0 5px 0 5px; +} +div.td-body { + padding:3px 5px 3px 5px; +} +div.comlist { + background-color:#FFFFFF; +} +div.comment-text { + padding:3px 5px 5px 15px; +} +div.comment-memo { + padding:0 0 0 15px; +} +div.staff { + color:#FFFFFF; + background-color:#1a1a1a; +} +a.staffnam { + color:#FFFFFF; +} +div.notice { + width:226px; + margin:7px 7px 3px 7px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#BCCDED; + background-color:#E5EEFE; +} +div.colorstar { + margin:7px 0 7px 0; +} +div.code-box{ + width:226px; + margin:7px 0 0 0; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#BCCDED; + background-color:#E5EEFE; +} +div.code-data{ + margin:7px 0 7px 0; +} +div.mail-reply { + width:226px; + margin:7px 7px 2px 7px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#BCCDED; + background-color:#E5EEFE; +} +div.lett_txt { + margin: 0 11px 0 11px; + border-style:solid; + border-width:0 2px 0 2px; + border-color:#92d300; + background-color:#ffffff; +} +div.lett_to { + margin: 0 11px 0 11px; + background-color:#92d300; + color:#ffffff; + padding: 1px 0 6px 5px; +} +div.pad0{ + padding: 0 0 0 0; +} +div.pad5t{ + padding: 5px 0 0 0; +} +div.pad5b{ + padding: 0 0 5px 0; +} +div.pad1b{ + padding: 0 0 1px 0; +} +div.pad2b{ + padding: 0 0 2px 0; +} +div.pad2{ + padding: 2px 2px 2px 2px; +} +div.pad5{ + padding: 5px 5px 5px 5px; +} +div.pad0-5{ + padding: 0 5px 0 5px; +} +td.pad2{ + padding: 2px 2px 2px 2px; +} +div.pad3-5{ + padding: 3px 5px 3px 5px; +} +div.lett_from{ + padding: 3px 11px 3px 0; +} +div.pad11{ + padding: 11px 11px 11px 11px; +} +div.pad5-11{ + padding: 5px 11px 5px 11px; +} +div.pad10b{ + padding: 0 0 10px 0; +} +div.pad20b{ + padding: 0 0 20px 0; +} +div.mar0-7{ + margin: 0px 7px 0px 7px; +} +div.mar0-11{ + margin: 0px 11px 0px 11px; +} +div.mar0{ + margin: 0px 0px 0px 0px; +} +div.mar5 { + margin: 5px 5px 5px 5px; +} +div.yaritori{ + margin: 0 11px 0 11px; + background-color:#ffffff; + border-style:solid; + border-width:0 2px 0 2px; + border-color:#92d300; +} +div.gr-tit{ + margin: 0 11px 0 11px; + background-color:#92d300; + color:#ffffff; +} +div.kadomaru{ + margin: 0 11px 0 11px; +} +div.lett-note{ + margin: 5px 11px 5px 11px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#92d300; + background-color:#ffffff; +} +div.pk{ + background-color:#ff3ab7; +} +div.blue{ + background-color:#3acfff; +} +div.gray{ + background-color:#cccccc; +} +div.gray_box{ + padding:5px; + border-style:solid; + border-width:1px; + border-color:#cccccc; + background-color:#ffffff; +} +div.vio-intro { + width:240px; + padding:7px 0 7px 7px; +} +div.vio-memo { + padding:0 0 10px 15px; +} +div.vio-text { + padding:0 0 10px 15px; +} +div.vio-note { + color:#999999; + padding:0 0 10px 15px; +} +div.vio-submit { + padding:10px 0 10px 0; +} +div.info-head { + padding:5px 7px 5px 7px; + border-style:solid; + border-width:0 0 1px 0; + border-color:#CCCCCC; + background-color:#eeeeee; +} +div.noborder{ + border-style:solid; + border-color:#CCCCCC; + border-width:0 0 0 0; +} +div.info-body { + padding:7px; +} +div.info-msg { + margin:0 0 7px 0; +} +div.news-head { + padding:5px 7px 5px 7px; + border-style:solid; + border-width:0 0 1px 0; + border-color:#CCCCCC; + background-color:#eeeeee; +} +div.news-body { + padding:7px; +} +div.news-h1 { + margin:7px 7px 0 7px; + padding:7px; + border-style:solid; + border-width:3px; + border-color:#91C900; +} +div.news-h2 { + padding:0 0 3px 7px; + border-style:solid; + border-width:0 0 1px 4px; + border-color:#91C900; +} +img.news-memo { + margin:0 10px 5px 0; + border-style:solid; + border-width:1px; + border-color:#CCCCCC; +} +div.info-h2 { + padding:0 0 3px 7px; + border-style:solid; + border-width:0 0 1px 4px; + border-color:#91C900; +} +div.num-box{ + background-color:#cccccc; + margin:0 30px; +} +td.tit-star{ + background-color:#e9f8c3; +} +img.help{ + border-style:solid; + border-width:2px; + border-color:#ffffff; +} +div.list{ + padding:0 0 5px 0; +} +div.star-det{ + padding:5px 0 5px 0; +} +img.sc{ + border-style:solid; + border-width:1px; + border-color:#cccccc; +} +td.border { + background-color: #82c300; +} +div.border { + border-style: solid; + border-width: 0 0 5px 0; + border-color: #82c300; +} +div.border-c { + border-style: solid; + border-width: 0 0 2px 0; + border-color: #82c300; +} +td.space { + background-color: #82c300; + color: #82c300; +} +td.tabon { + color: #82c300; +} +td.taboff { + background-color: #82c300; + color: #ffffff; +} +td.tabpager { + background-color: #82c300; + color: #ffffff; +} +div.on { + padding: 1px 6px 3px 6px; +} +span.border { + color: #b2db59; +} +span.border-gray { + color: #cccccc; +} +a.taboff { + color: #ffffff; +} +div.comme { + padding: 3px 3px 3px 12px; + color: #b2db59; +} +span.text { + color: #333333; +} +td.gray { + background-color: #f2f2f2; +} +div.message { + width:226px; + margin:7px 7px 2px 7px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#BCCDED; + background-color:#E5EEFE; +} +div.error-message { + width:226px; + margin:7px 7px 2px 7px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#F5C8A7; + background-color:#FFEED8; + color:#9B2E2E; +} +div.ok-message { + width:226px; + margin:7px 7px 2px 7px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#C5DABA; + background-color:#E3F9DB; + color:#517B29; +} +div.guide-h2 { + padding:0 0 3px 7px; + border-style:solid; + border-width:0 0 1px 4px; + border-color:#66ccff; +} +div.guide-h3 { + padding:3px 3px 3px 3px; + background-color:#66ccff; + color: #ffffff; +} +div.select-t { + color: #66ccff; + padding: 0 0 3px 0; +} +div.select-b { + padding:5px 3px 5px 3px; + border-style: solid; + border-width: 1px 1px 1px 1px; + border-color: #99ccff; + background-color: #ffffff; +} +span.border-s { + color: #99ccff; +} +span.color { + color: #ffffff; +} +div.credit { + padding:5px 7px 5px 7px; + background-color:#eeeeee; +} +div.rule-tit { + background-color: #82c300; + color: #ffffff; + padding: 3px 3px 3px 3px; +} +div.rule-ind { + margin: 0 0 0 10px; +} +div.hr-prof { + border-style:solid; + border-width:0 0 3px 0; + border-color:transparent; +} +table.send { + margin: 5px 0 0 0 ; +} +div.icon { + border-style: solid; + border-width: 1px 1px 1px 1px; + border-color: #cccccc; +} +td.username { + height:20px; +} +td.mystatus { +} +div.prev { + padding: 1px 0 5px 0; +} +div.next { + padding: 5px 0 1px 0; +} +div.prof-det{ + padding: 0 5px 0 5px; +} +div.catch { + margin: 5px 5px 5px 5px; + padding: 5px 5px 5px 5px; + border-style: solid; + border-width: 2px 2px 2px 2px; + border-color: #ffffff; +} +a.still { + color: #ffffff; +} +div.head { + margin: 0px 0 0 0; +} +div.send { + margin: 0px 10px 3px 11px; +} +div.link { + margin: 0px 10px 0 11px; +} +img.button { + margin: 5px 0 0 0; +} +td.theme { + margin: 0 0 0 3px; +} +div.trial-h1 { + margin: 5px 0 5px 0; + padding:3px; + border-style:solid; + border-width:3px; + border-color:#91C900; +} +div.mar-b10{ +margin:0 0 10px 0; +} +div.cam1{ + margin:7px 7px 0 7px; + padding:7px; + background-color: #ff2828; + color: #ffffff; +} +div.cam2{ + margin:0 7px 0 7px; + padding:7px; + border-style:solid; + border-width: 2px 2px 2px 2px; + border-color: #ff2828; +} +table.xmas2009{ + margin: 0 10px 0 11px; + background-color: #c70606; + color: #ffffff; +} +div.yellow { + margin: 0 11px 0 11px; + background-color:#ffe800; +} +div.sttr_mes { + width:226px; + margin:7px 7px 0px 7px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#92cb22; + background-color:#ffffff; +} +div.sttr_gacha { + width:226px; + margin:7px 7px 0px 7px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#ea475c; + background-color:#ffffff; +} +div.compsp { + width:226px; + margin:7px 7px 0px 7px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#ffe800; + background-color:#fff9b7; +} +div.sttr_war { + width:226px; + margin:7px 7px 0px 7px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#F5C8A7; + background-color:#FFEED8; + color:#9B2E2E; +} +div.sttr_price { + background-color:#FF9933; + color: #ffffff; +} +div.sttr_item { + width:226px; + margin:0px 7px 0px 7px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#92cb22; + background-color:#ffffff; +} +div.sttr_theme { + width:226px; + margin:0px 7px 3px 7px; + padding:5px; + border-style:solid; + border-width:0px 1px 1px 1px; + border-color:#92cb22; + background-color:#ffffff; +} +div.sttr_back { + width:226px; + margin:0px 7px 0px 7px; +} +div.gift_l { + margin: 0 11px 0 11px; + border-style:solid; + border-width:0 2px 0px 2px; + border-color:#ff5252; +} +div.gift_h { + margin: 0 11px 0 11px; + border-style:solid; + border-width:0 2px 0px 2px; + border-color:#ffd616; +} +img.shop_icon { + margin:0 1px 1px 0; +} +div.help_guide { + border-style:solid; + border-width:0 1px 1px 1px; + border-color:#ffac3e; +} +div.guide-head { + color: #ffffff; + background-color: #5abcea; +} +div.guide-title { + color: #ffffff; + background-color: #5abcea; +} +div.guide-main { + border-style:solid; + border-width:0 1px 1px 1px; + border-color:#5abcea; +} +div.green-title { + color: #ffffff; + background-color: #91C900; +} +div.green-main { + border-style:solid; + border-width:0 1px 1px 1px; + border-color:#91C900; +} +table.method{ + border-style:solid; + border-width:1px; + border-color:#cccccc; +} +div.search { + background-color: #eeeeee; + border-style: solid; + border-width: 1px; + border-color:#cccccc; +} +td.keyboard { + background-color: #eeeeee; +} +table.key-tab{ + margin: 0 6px 0 6px; +} +div.keyout { + margin: 0 7px 0 7px; + border-style: solid; + border-width: 0 1px 1px 1px; + border-color:#cccccc; +} +div.on-ja { + border-style: solid; + border-width: 1px 1px 0 1px; + border-color:#cccccc; +} +div.off-en { + border-style: solid; + border-width: 1px 1px 0 0; + border-color:#cccccc; +} +div.off-aa { + border-style: solid; + border-width: 1px 1px 0 0; + border-color:#cccccc; +} +table.camp-detail { + border-style: solid; + border-width: 1px; + border-color:#cccccc; +} +table.center { + margin: 0 15px 0 16px; +} +div.codeborder { + border-style: solid; + border-width:0 1px 1px 1px; + border-color:#82c300; +} +div.codeprev { + border-style: solid; + border-width:1px; + border-color:#82c300; +} +td.code { + background-color:#ffffff; +} +table.codetab { + border-style: solid; + border-width: 1px 1px 0 1px; + border-color:#82c300; +} +div.codetab { + border-style: solid; + border-width: 0 1px 1px 1px; + border-color:#82c300; + background-color:#ffffff; +} +div.c_tab2 { + border-style: solid; + border-width: 1px 1px 1px 1px; + border-color:#82c300; + background-color:#ffffff; +} +div.topic { + border-style:solid; + border-width:1px; + border-color:#fff273; + background-color:#fff8b2; +} +div.icon-green { + border-style: solid; + border-width: 1px 1px 1px 1px; + border-color: #82c300; +} +div.p-block { + border-style:solid; + border-width:1px; + border-color:#000000; + color:#000000; + background-color:#ffffff; +} +div.clstar-help{ + background-color:#ffffff; + color:#82c300; +} +div.ugo4th{ + border-style:solid; + border-width:1px; + border-color:#c4260f; + background-color:#d52515; +} diff --git a/hatenadir/css/ds/camp100618.css b/hatenadir/css/ds/camp100618.css new file mode 100644 index 0000000..24246c6 --- /dev/null +++ b/hatenadir/css/ds/camp100618.css @@ -0,0 +1,863 @@ +@charset "UTF-8"; +div.head { + margin: 10px 0 0 0; +} +a { + color:#e63333; +} +table.profbox { + background-color: #353535; + color: #ffffff; +} +div.prof_out { + margin: 0 11px 0 11px; + background-color: #353535; + border-style: solid; + border-width: 0 1px 0 1px; + border-color: #6c8ff2; +} +span.more-f{ + color: #e63333; +} +div.notice2 { + margin:0 11px 5px 11px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#139a2f; + background-color:#ffffff; +} +td.border{ + background-color: #000000; +} +div.border { + border-style: solid; + border-width: 0 0 5px 0; + border-color: #000000; +} +div.border-c { + border-style: solid; + border-width: 0 0 2px 0; + border-color: #000000; +} +td.space { + background-color: #000000; +} +td.tabon { + color: #ed5151; +} +td.taboff { + background-color: #000000; + color: #ed5151; +} +td.tabpager { + background-color: #000000; + color: #ed5151; +} +span.url{ + text-decoration:underline; +} +span.comptxt { + color:#ff8a00; +} +span.star0 { + color:#fdc556; +} +span.star1 { + color:#138200; +} +span.star2 { + color:#ff455c; +} +span.star3 { + color:#00b0f9; +} +span.star4 { + color:#a411b9; +} +span.star0c { + color:#fdc556; +} +span.star1c { + color:#138200; +} +span.star2c { + color:#ff455c; +} +span.star3c { + color:#00b0f9; +} +span.star4c { + color:#a411b9; +} +span.orange{ + color: #ff8d45; +} +span.green { + color: #82c300; +} +span.gray{ + color: #666666; +} +span.white { + color:#FFFFFF; +} +html { + margin:0; + padding:0; +} +body { + color:#333333; + margin:0; + padding:0; +} +div.title { + margin:0 7px 0 7px; + padding:7px 5px 7px 5px; + border-style:solid; + border-width:0 0 1px 0; + border-color:#CCCCCC; +} +div.description { + margin:0 7px 0 7px; + padding:7px 5px 7px 5px; + border-style:solid; + border-width:0 0 1px 0; + border-color:#CCCCCC; +} +div.hr { + border-style:solid; + border-width:0 0 1px 0; + border-color:#CCCCCC; +} +div.hr-tab { + border-style:solid; + border-width:0 0 1px 0; + border-color:#82c300; +} +span.timestamp { + color:#999999; +} +a.timestamp { + color:#999999; +} +a.violation { + color:#333333; +} +div.box { + padding:7px; + border-style:solid; + border-width:1px; + border-color:#CCCCCC; + background-color:#FFFFFF; +} +div.more { + margin:7px 0 0 0; +} +div.pager { + padding:5px; +} +div.num { + margin:5px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#CCCCCC; + background-color:#FFFFFF; +} +span.new { + color: #cc0000; +} +span.price { + color: #92cb22; +} +span.date { + color: #cccccc; +} +table.detail{ + margin:0 7px 0 7px; +} +table.fullsize { + margin:0; +} +div.item-term { + padding:3px 0 3px 5px; +} +div.item-value { + padding:3px 5px 3px 0; +} +div.item-text { + padding:3px 5px 3px 15px; +} +div.item-tcom { + padding: 3px 5px 0 5px; +} +div.item-com { + padding: 0 5px 0 5px; +} +div.td-body { + padding:3px 5px 3px 5px; +} +div.comlist { + background-color:#FFFFFF; +} +div.comment-text { + padding:3px 5px 5px 15px; +} +div.comment-memo { + padding:0 0 0 15px; +} +div.staff { + color:#FFFFFF; + background-color:#1a1a1a; +} +a.staffnam { + color:#FFFFFF; +} +div.notice { + width:226px; + margin:7px 7px 3px 7px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#BCCDED; + background-color:#E5EEFE; +} +div.colorstar { + margin:7px 0 7px 0; +} +div.code-box{ + width:226px; + margin:7px 0 0 0; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#BCCDED; + background-color:#E5EEFE; +} +div.code-data{ + margin:7px 0 7px 0; +} +div.mail-reply { + width:226px; + margin:7px 7px 2px 7px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#BCCDED; + background-color:#E5EEFE; +} +div.lett_txt { + margin: 0 11px 0 11px; + border-style:solid; + border-width:0 2px 0 2px; + border-color:#92d300; + background-color:#ffffff; +} +div.lett_to { + margin: 0 11px 0 11px; + background-color:#92d300; + color:#ffffff; + padding: 1px 0 6px 5px; +} +div.pad0{ + padding: 0 0 0 0; +} +div.pad5t{ + padding: 5px 0 0 0; +} +div.pad5b{ + padding: 0 0 5px 0; +} +div.pad1b{ + padding: 0 0 1px 0; +} +div.pad2b{ + padding: 0 0 2px 0; +} +div.pad2{ + padding: 2px 2px 2px 2px; +} +div.pad5{ + padding: 5px 5px 5px 5px; +} +div.pad0-5{ + padding: 0 5px 0 5px; +} +td.pad2{ + padding: 2px 2px 2px 2px; +} +div.pad3-5{ + padding: 3px 5px 3px 5px; +} +div.lett_from{ + padding: 3px 11px 3px 0; +} +div.pad11{ + padding: 11px 11px 11px 11px; +} +div.pad5-11{ + padding: 5px 11px 5px 11px; +} +div.pad10b{ + padding: 0 0 10px 0; +} +div.pad20b{ + padding: 0 0 20px 0; +} +div.mar0-7{ + margin: 0px 7px 0px 7px; +} +div.mar0-11{ + margin: 0px 11px 0px 11px; +} +div.mar0{ + margin: 0px 0px 0px 0px; +} +div.mar5 { + margin: 5px 5px 5px 5px; +} +div.yaritori{ + margin: 0 11px 0 11px; + background-color:#ffffff; + border-style:solid; + border-width:0 2px 0 2px; + border-color:#92d300; +} +div.gr-tit{ + margin: 0 11px 0 11px; + background-color:#92d300; + color:#ffffff; +} +div.kadomaru{ + margin: 0 11px 0 11px; +} +div.lett-note{ + margin: 5px 11px 5px 11px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#92d300; + background-color:#ffffff; +} +div.pk{ + background-color:#ff3ab7; +} +div.blue{ + background-color:#3acfff; +} +div.gray{ + background-color:#cccccc; +} +div.gray_box{ + padding:5px; + border-style:solid; + border-width:1px; + border-color:#cccccc; + background-color:#ffffff; +} +div.vio-intro { + width:240px; + padding:7px 0 7px 7px; +} +div.vio-memo { + padding:0 0 10px 15px; +} +div.vio-text { + padding:0 0 10px 15px; +} +div.vio-note { + color:#999999; + padding:0 0 10px 15px; +} +div.vio-submit { + padding:10px 0 10px 0; +} +div.info-head { + padding:5px 7px 5px 7px; + border-style:solid; + border-width:0 0 1px 0; + border-color:#CCCCCC; + background-color:#eeeeee; +} +div.noborder{ + border-style:solid; + border-color:#CCCCCC; + border-width:0 0 0 0; +} +div.info-body { + padding:7px; +} +div.info-msg { + margin:0 0 7px 0; +} +div.news-head { + padding:5px 7px 5px 7px; + border-style:solid; + border-width:0 0 1px 0; + border-color:#CCCCCC; + background-color:#eeeeee; +} +div.news-body { + padding:7px; +} +div.news-h1 { + margin:7px 7px 0 7px; + padding:7px; + border-style:solid; + border-width:3px; + border-color:#91C900; +} +div.news-h2 { + padding:0 0 3px 7px; + border-style:solid; + border-width:0 0 1px 4px; + border-color:#91C900; +} +img.news-memo { + margin:0 10px 5px 0; + border-style:solid; + border-width:1px; + border-color:#CCCCCC; +} +div.info-h2 { + padding:0 0 3px 7px; + border-style:solid; + border-width:0 0 1px 4px; + border-color:#91C900; +} +div.num-box{ + background-color:#cccccc; + margin:0 30px; +} +td.tit-star{ + background-color:#e9f8c3; +} +img.help{ + border-style:solid; + border-width:2px; + border-color:#ffffff; +} +div.list{ + padding:0 0 5px 0; +} +div.star-det{ + padding:5px 0 5px 0; +} +img.sc{ + border-style:solid; + border-width:1px; + border-color:#cccccc; +} +td.border { + background-color: #82c300; +} +div.border { + border-style: solid; + border-width: 0 0 5px 0; + border-color: #82c300; +} +div.border-c { + border-style: solid; + border-width: 0 0 2px 0; + border-color: #82c300; +} +td.space { + background-color: #82c300; + color: #82c300; +} +td.tabon { + color: #82c300; +} +td.taboff { + background-color: #82c300; + color: #ffffff; +} +td.tabpager { + background-color: #82c300; + color: #ffffff; +} +div.on { + padding: 1px 6px 3px 6px; +} +span.border { + color: #b2db59; +} +span.border-gray { + color: #cccccc; +} +a.taboff { + color: #ffffff; +} +div.comme { + padding: 3px 3px 3px 12px; + color: #b2db59; +} +span.text { + color: #333333; +} +td.gray { + background-color: #f2f2f2; +} +div.message { + width:226px; + margin:7px 7px 2px 7px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#BCCDED; + background-color:#E5EEFE; +} +div.error-message { + width:226px; + margin:7px 7px 2px 7px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#F5C8A7; + background-color:#FFEED8; + color:#9B2E2E; +} +div.ok-message { + width:226px; + margin:7px 7px 2px 7px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#C5DABA; + background-color:#E3F9DB; + color:#517B29; +} +div.guide-h2 { + padding:0 0 3px 7px; + border-style:solid; + border-width:0 0 1px 4px; + border-color:#66ccff; +} +div.guide-h3 { + padding:3px 3px 3px 3px; + background-color:#66ccff; + color: #ffffff; +} +div.select-t { + color: #66ccff; + padding: 0 0 3px 0; +} +div.select-b { + padding:5px 3px 5px 3px; + border-style: solid; + border-width: 1px 1px 1px 1px; + border-color: #99ccff; + background-color: #ffffff; +} +span.border-s { + color: #99ccff; +} +span.color { + color: #ffffff; +} +div.credit { + padding:5px 7px 5px 7px; + background-color:#eeeeee; +} +div.rule-tit { + background-color: #82c300; + color: #ffffff; + padding: 3px 3px 3px 3px; +} +div.rule-ind { + margin: 0 0 0 10px; +} +div.hr-prof { + border-style:solid; + border-width:0 0 3px 0; + border-color:transparent; +} +table.send { + margin: 5px 0 0 0 ; +} +div.icon { + border-style: solid; + border-width: 1px 1px 1px 1px; + border-color: #cccccc; +} +td.username { + height:20px; +} +td.mystatus { +} +div.prev { + padding: 1px 0 5px 0; +} +div.next { + padding: 5px 0 1px 0; +} +div.prof-det{ + padding: 0 5px 0 5px; +} +div.catch { + margin: 5px 5px 5px 5px; + padding: 5px 5px 5px 5px; + border-style: solid; + border-width: 2px 2px 2px 2px; + border-color: #ffffff; +} +a.still { + color: #ffffff; +} +div.head { + margin: 0px 0 0 0; +} +div.send { + margin: 0px 10px 3px 11px; +} +div.link { + margin: 0px 10px 0 11px; +} +img.button { + margin: 5px 0 0 0; +} +td.theme { + margin: 0 0 0 3px; +} +div.trial-h1 { + margin: 5px 0 5px 0; + padding:3px; + border-style:solid; + border-width:3px; + border-color:#91C900; +} +div.mar-b10{ +margin:0 0 10px 0; +} +div.cam1{ + margin:7px 7px 0 7px; + padding:7px; + background-color: #ff2828; + color: #ffffff; +} +div.cam2{ + margin:0 7px 0 7px; + padding:7px; + border-style:solid; + border-width: 2px 2px 2px 2px; + border-color: #ff2828; +} +table.xmas2009{ + margin: 0 10px 0 11px; + background-color: #c70606; + color: #ffffff; +} +div.yellow { + margin: 0 11px 0 11px; + background-color:#ffe800; +} +div.sttr_mes { + width:226px; + margin:7px 7px 0px 7px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#92cb22; + background-color:#ffffff; +} +div.sttr_gacha { + width:226px; + margin:7px 7px 0px 7px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#ea475c; + background-color:#ffffff; +} +div.compsp { + width:226px; + margin:7px 7px 0px 7px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#ffe800; + background-color:#fff9b7; +} +div.sttr_war { + width:226px; + margin:7px 7px 0px 7px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#F5C8A7; + background-color:#FFEED8; + color:#9B2E2E; +} +div.sttr_price { + background-color:#FF9933; + color: #ffffff; +} +div.sttr_item { + width:226px; + margin:0px 7px 0px 7px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#92cb22; + background-color:#ffffff; +} +div.sttr_theme { + width:226px; + margin:0px 7px 3px 7px; + padding:5px; + border-style:solid; + border-width:0px 1px 1px 1px; + border-color:#92cb22; + background-color:#ffffff; +} +div.sttr_back { + width:226px; + margin:0px 7px 0px 7px; +} +div.gift_l { + margin: 0 11px 0 11px; + border-style:solid; + border-width:0 2px 0px 2px; + border-color:#ff5252; +} +div.gift_h { + margin: 0 11px 0 11px; + border-style:solid; + border-width:0 2px 0px 2px; + border-color:#ffd616; +} +img.shop_icon { + margin:0 1px 1px 0; +} +div.help_guide { + border-style:solid; + border-width:0 1px 1px 1px; + border-color:#ffac3e; +} +div.guide-head { + color: #ffffff; + background-color: #5abcea; +} +div.guide-title { + color: #ffffff; + background-color: #5abcea; +} +div.guide-main { + border-style:solid; + border-width:0 1px 1px 1px; + border-color:#5abcea; +} +div.green-title { + color: #ffffff; + background-color: #91C900; +} +div.green-main { + border-style:solid; + border-width:0 1px 1px 1px; + border-color:#91C900; +} +table.method{ + border-style:solid; + border-width:1px; + border-color:#cccccc; +} +div.search { + background-color: #eeeeee; + border-style: solid; + border-width: 1px; + border-color:#cccccc; +} +td.keyboard { + background-color: #eeeeee; +} +table.key-tab{ + margin: 0 6px 0 6px; +} +div.keyout { + margin: 0 7px 0 7px; + border-style: solid; + border-width: 0 1px 1px 1px; + border-color:#cccccc; +} +div.on-ja { + border-style: solid; + border-width: 1px 1px 0 1px; + border-color:#cccccc; +} +div.off-en { + border-style: solid; + border-width: 1px 1px 0 0; + border-color:#cccccc; +} +div.off-aa { + border-style: solid; + border-width: 1px 1px 0 0; + border-color:#cccccc; +} +table.camp-detail { + border-style: solid; + border-width: 1px; + border-color:#cccccc; +} +table.center { + margin: 0 15px 0 16px; +} +div.codeborder { + border-style: solid; + border-width:0 1px 1px 1px; + border-color:#82c300; +} +div.codeprev { + border-style: solid; + border-width:1px; + border-color:#82c300; +} +td.code { + background-color:#ffffff; +} +table.codetab { + border-style: solid; + border-width: 1px 1px 0 1px; + border-color:#82c300; +} +div.codetab { + border-style: solid; + border-width: 0 1px 1px 1px; + border-color:#82c300; + background-color:#ffffff; +} +div.c_tab2 { + border-style: solid; + border-width: 1px 1px 1px 1px; + border-color:#82c300; + background-color:#ffffff; +} +div.topic { + border-style:solid; + border-width:1px; + border-color:#fff273; + background-color:#fff8b2; +} +div.icon-green { + border-style: solid; + border-width: 1px 1px 1px 1px; + border-color: #82c300; +} +div.p-block { + border-style:solid; + border-width:1px; + border-color:#000000; + color:#000000; + background-color:#ffffff; +} +div.clstar-help{ + background-color:#ffffff; + color:#82c300; +} +div.ugo4th{ + border-style:solid; + border-width:1px; + border-color:#c4260f; + background-color:#d52515; +} diff --git a/hatenadir/css/ds/common.css b/hatenadir/css/ds/common.css new file mode 100644 index 0000000..04949bb --- /dev/null +++ b/hatenadir/css/ds/common.css @@ -0,0 +1,808 @@ +@charset "UTF-8"; +span.url{ + text-decoration:underline; +} +span.comptxt { + color:#ff8a00; +} +span.star0 { + color:#fdc556; +} +span.star1 { + color:#138200; +} +span.star2 { + color:#ff455c; +} +span.star3 { + color:#00b0f9; +} +span.star4 { + color:#a411b9; +} +span.star0c { + color:#fdc556; +} +span.star1c { + color:#138200; +} +span.star2c { + color:#ff455c; +} +span.star3c { + color:#00b0f9; +} +span.star4c { + color:#a411b9; +} +span.orange{ + color: #ff8d45; +} +span.green { + color: #82c300; +} +span.gray{ + color: #666666; +} +span.white { + color:#FFFFFF; +} +html { + margin:0; + padding:0; +} +body { + color:#333333; + margin:0; + padding:0; +} +div.title { + margin:0 7px 0 7px; + padding:7px 5px 7px 5px; + border-style:solid; + border-width:0 0 1px 0; + border-color:#CCCCCC; +} +div.description { + margin:0 7px 0 7px; + padding:7px 5px 7px 5px; + border-style:solid; + border-width:0 0 1px 0; + border-color:#CCCCCC; +} +div.hr { + border-style:solid; + border-width:0 0 1px 0; + border-color:#CCCCCC; +} +div.hr-tab { + border-style:solid; + border-width:0 0 1px 0; + border-color:#82c300; +} +span.timestamp { + color:#999999; +} +a.timestamp { + color:#999999; +} +a.violation { + color:#333333; +} +div.box { + padding:7px; + border-style:solid; + border-width:1px; + border-color:#CCCCCC; + background-color:#FFFFFF; +} +div.more { + margin:7px 0 0 0; +} +div.pager { + padding:5px; +} +div.num { + margin:5px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#CCCCCC; + background-color:#FFFFFF; +} +span.new { + color: #cc0000; +} +span.price { + color: #92cb22; +} +span.date { + color: #cccccc; +} +table.detail{ + margin:0 7px 0 7px; +} +table.fullsize { + margin:0; +} +div.item-term { + padding:3px 0 3px 5px; +} +div.item-value { + padding:3px 5px 3px 0; +} +div.item-text { + padding:3px 5px 3px 15px; +} +div.item-tcom { + padding: 3px 5px 0 5px; +} +div.item-com { + padding: 0 5px 0 5px; +} +div.td-body { + padding:3px 5px 3px 5px; +} +div.comlist { + background-color:#FFFFFF; +} +div.comment-text { + padding:3px 5px 5px 15px; +} +div.comment-memo { + padding:0 0 0 15px; +} +div.staff { + color:#FFFFFF; + background-color:#1a1a1a; +} +a.staffnam { + color:#FFFFFF; +} +div.notice { + width:226px; + margin:7px 7px 3px 7px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#BCCDED; + background-color:#E5EEFE; +} +div.colorstar { + margin:7px 0 7px 0; +} +div.code-box{ + width:226px; + margin:7px 0 0 0; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#BCCDED; + background-color:#E5EEFE; +} +div.code-data{ + margin:7px 0 7px 0; +} +div.mail-reply { + width:226px; + margin:7px 7px 2px 7px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#BCCDED; + background-color:#E5EEFE; +} +div.lett_txt { + margin: 0 11px 0 11px; + border-style:solid; + border-width:0 2px 0 2px; + border-color:#92d300; + background-color:#ffffff; +} +div.lett_to { + margin: 0 11px 0 11px; + background-color:#92d300; + color:#ffffff; + padding: 1px 0 6px 5px; +} +div.pad0{ + padding: 0 0 0 0; +} +div.pad5t{ + padding: 5px 0 0 0; +} +div.pad5b{ + padding: 0 0 5px 0; +} +div.pad1b{ + padding: 0 0 1px 0; +} +div.pad2b{ + padding: 0 0 2px 0; +} +div.pad2{ + padding: 2px 2px 2px 2px; +} +div.pad5{ + padding: 5px 5px 5px 5px; +} +div.pad0-5{ + padding: 0 5px 0 5px; +} +td.pad2{ + padding: 2px 2px 2px 2px; +} +div.pad3-5{ + padding: 3px 5px 3px 5px; +} +div.lett_from{ + padding: 3px 11px 3px 0; +} +div.pad11{ + padding: 11px 11px 11px 11px; +} +div.pad5-11{ + padding: 5px 11px 5px 11px; +} +div.pad10b{ + padding: 0 0 10px 0; +} +div.pad20b{ + padding: 0 0 20px 0; +} +div.mar0-7{ + margin: 0px 7px 0px 7px; +} +div.mar0-11{ + margin: 0px 11px 0px 11px; +} +div.mar0{ + margin: 0px 0px 0px 0px; +} +div.mar5 { + margin: 5px 5px 5px 5px; +} +div.yaritori{ + margin: 0 11px 0 11px; + background-color:#ffffff; + border-style:solid; + border-width:0 2px 0 2px; + border-color:#92d300; +} +div.gr-tit{ + margin: 0 11px 0 11px; + background-color:#92d300; + color:#ffffff; +} +div.kadomaru{ + margin: 0 11px 0 11px; +} +div.lett-note{ + margin: 5px 11px 5px 11px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#92d300; + background-color:#ffffff; +} +div.pk{ + background-color:#ff3ab7; +} +div.blue{ + background-color:#3acfff; +} +div.gray{ + background-color:#cccccc; +} +div.gray_box{ + padding:5px; + border-style:solid; + border-width:1px; + border-color:#cccccc; + background-color:#ffffff; +} +div.vio-intro { + width:240px; + padding:7px 0 7px 7px; +} +div.vio-memo { + padding:0 0 10px 15px; +} +div.vio-text { + padding:0 0 10px 15px; +} +div.vio-note { + color:#999999; + padding:0 0 10px 15px; +} +div.vio-submit { + padding:10px 0 10px 0; +} +div.info-head { + padding:5px 7px 5px 7px; + border-style:solid; + border-width:0 0 1px 0; + border-color:#CCCCCC; + background-color:#eeeeee; +} +div.noborder{ + border-style:solid; + border-color:#CCCCCC; + border-width:0 0 0 0; +} +div.info-body { + padding:7px; +} +div.info-msg { + margin:0 0 7px 0; +} +div.news-head { + padding:5px 7px 5px 7px; + border-style:solid; + border-width:0 0 1px 0; + border-color:#CCCCCC; + background-color:#eeeeee; +} +div.news-body { + padding:7px; +} +div.news-h1 { + margin:7px 7px 0 7px; + padding:7px; + border-style:solid; + border-width:3px; + border-color:#91C900; +} +div.news-h2 { + padding:0 0 3px 7px; + border-style:solid; + border-width:0 0 1px 4px; + border-color:#91C900; +} +img.news-memo { + margin:0 10px 5px 0; + border-style:solid; + border-width:1px; + border-color:#CCCCCC; +} +div.info-h2 { + padding:0 0 3px 7px; + border-style:solid; + border-width:0 0 1px 4px; + border-color:#91C900; +} +div.num-box{ + background-color:#cccccc; + margin:0 30px; +} +td.tit-star{ + background-color:#e9f8c3; +} +img.help{ + border-style:solid; + border-width:2px; + border-color:#ffffff; +} +div.list{ + padding:0 0 5px 0; +} +div.star-det{ + padding:5px 0 5px 0; +} +img.sc{ + border-style:solid; + border-width:1px; + border-color:#cccccc; +} +td.border { + background-color: #82c300; +} +div.border { + border-style: solid; + border-width: 0 0 5px 0; + border-color: #82c300; +} +div.border-c { + border-style: solid; + border-width: 0 0 2px 0; + border-color: #82c300; +} +td.space { + background-color: #82c300; + color: #82c300; +} +td.tabon { + color: #82c300; +} +td.taboff { + background-color: #82c300; + color: #ffffff; +} +td.tabpager { + background-color: #82c300; + color: #ffffff; +} +div.on { + padding: 1px 6px 3px 6px; +} +span.border { + color: #b2db59; +} +span.border-gray { + color: #cccccc; +} +a.taboff { + color: #ffffff; +} +div.comme { + padding: 3px 3px 3px 12px; + color: #b2db59; +} +span.text { + color: #333333; +} +td.gray { + background-color: #f2f2f2; +} +div.message { + width:226px; + margin:7px 7px 2px 7px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#BCCDED; + background-color:#E5EEFE; +} +div.error-message { + width:226px; + margin:7px 7px 2px 7px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#F5C8A7; + background-color:#FFEED8; + color:#9B2E2E; +} +div.ok-message { + width:226px; + margin:7px 7px 2px 7px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#C5DABA; + background-color:#E3F9DB; + color:#517B29; +} +div.guide-h2 { + padding:0 0 3px 7px; + border-style:solid; + border-width:0 0 1px 4px; + border-color:#66ccff; +} +div.guide-h3 { + padding:3px 3px 3px 3px; + background-color:#66ccff; + color: #ffffff; +} +div.select-t { + color: #66ccff; + padding: 0 0 3px 0; +} +div.select-b { + padding:5px 3px 5px 3px; + border-style: solid; + border-width: 1px 1px 1px 1px; + border-color: #99ccff; + background-color: #ffffff; +} +span.border-s { + color: #99ccff; +} +span.color { + color: #ffffff; +} +div.credit { + padding:5px 7px 5px 7px; + background-color:#eeeeee; +} +div.rule-tit { + background-color: #82c300; + color: #ffffff; + padding: 3px 3px 3px 3px; +} +div.rule-ind { + margin: 0 0 0 10px; +} +div.hr-prof { + border-style:solid; + border-width:0 0 3px 0; + border-color:transparent; +} +table.send { + margin: 5px 0 0 0 ; +} +div.icon { + border-style: solid; + border-width: 1px 1px 1px 1px; + border-color: #cccccc; +} +td.username { + height:20px; +} +td.mystatus { +} +div.prev { + padding: 1px 0 5px 0; +} +div.next { + padding: 5px 0 1px 0; +} +div.prof-det{ + padding: 0 5px 0 5px; +} +div.catch { + margin: 5px 5px 5px 5px; + padding: 5px 5px 5px 5px; + border-style: solid; + border-width: 2px 2px 2px 2px; + border-color: #ffffff; +} +a.still { + color: #ffffff; +} +div.head { + margin: 0px 0 0 0; +} +div.send { + margin: 0px 10px 3px 11px; +} +div.link { + margin: 0px 10px 0 11px; +} +img.button { + margin: 5px 0 0 0; +} +td.theme { + margin: 0 0 0 3px; +} +div.trial-h1 { + margin: 5px 0 5px 0; + padding:3px; + border-style:solid; + border-width:3px; + border-color:#91C900; +} +div.mar-b10{ +margin:0 0 10px 0; +} +div.cam1{ + margin:7px 7px 0 7px; + padding:7px; + background-color: #ff2828; + color: #ffffff; +} +div.cam2{ + margin:0 7px 0 7px; + padding:7px; + border-style:solid; + border-width: 2px 2px 2px 2px; + border-color: #ff2828; +} +table.xmas2009{ + margin: 0 10px 0 11px; + background-color: #c70606; + color: #ffffff; +} +div.yellow { + margin: 0 11px 0 11px; + background-color:#ffe800; +} +div.sttr_mes { + width:226px; + margin:7px 7px 0px 7px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#92cb22; + background-color:#ffffff; +} +div.sttr_gacha { + width:226px; + margin:7px 7px 0px 7px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#ea475c; + background-color:#ffffff; +} +div.compsp { + width:226px; + margin:7px 7px 0px 7px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#ffe800; + background-color:#fff9b7; +} +div.sttr_war { + width:226px; + margin:7px 7px 0px 7px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#F5C8A7; + background-color:#FFEED8; + color:#9B2E2E; +} +div.sttr_price { + background-color:#FF9933; + color: #ffffff; +} +div.sttr_item { + width:226px; + margin:0px 7px 0px 7px; + padding:5px; + border-style:solid; + border-width:1px; + border-color:#92cb22; + background-color:#ffffff; +} +div.sttr_theme { + width:226px; + margin:0px 7px 3px 7px; + padding:5px; + border-style:solid; + border-width:0px 1px 1px 1px; + border-color:#92cb22; + background-color:#ffffff; +} +div.sttr_back { + width:226px; + margin:0px 7px 0px 7px; +} +div.gift_l { + margin: 0 11px 0 11px; + border-style:solid; + border-width:0 2px 0px 2px; + border-color:#ff5252; +} +div.gift_h { + margin: 0 11px 0 11px; + border-style:solid; + border-width:0 2px 0px 2px; + border-color:#ffd616; +} +img.shop_icon { + margin:0 1px 1px 0; +} +div.help_guide { + border-style:solid; + border-width:0 1px 1px 1px; + border-color:#ffac3e; +} +div.guide-head { + color: #ffffff; + background-color: #5abcea; +} +div.guide-title { + color: #ffffff; + background-color: #5abcea; +} +div.guide-main { + border-style:solid; + border-width:0 1px 1px 1px; + border-color:#5abcea; +} +div.green-title { + color: #ffffff; + background-color: #91C900; +} +div.green-main { + border-style:solid; + border-width:0 1px 1px 1px; + border-color:#91C900; +} +table.method{ + border-style:solid; + border-width:1px; + border-color:#cccccc; +} +div.search { + background-color: #eeeeee; + border-style: solid; + border-width: 1px; + border-color:#cccccc; +} +td.keyboard { + background-color: #eeeeee; +} +table.key-tab{ + margin: 0 6px 0 6px; +} +div.keyout { + margin: 0 7px 0 7px; + border-style: solid; + border-width: 0 1px 1px 1px; + border-color:#cccccc; +} +div.on-ja { + border-style: solid; + border-width: 1px 1px 0 1px; + border-color:#cccccc; +} +div.off-en { + border-style: solid; + border-width: 1px 1px 0 0; + border-color:#cccccc; +} +div.off-aa { + border-style: solid; + border-width: 1px 1px 0 0; + border-color:#cccccc; +} +table.camp-detail { + border-style: solid; + border-width: 1px; + border-color:#cccccc; +} +table.center { + margin: 0 15px 0 16px; +} +div.codeborder { + border-style: solid; + border-width:0 1px 1px 1px; + border-color:#82c300; +} +div.codeprev { + border-style: solid; + border-width:1px; + border-color:#82c300; +} +td.code { + background-color:#ffffff; +} +table.codetab { + border-style: solid; + border-width: 1px 1px 0 1px; + border-color:#82c300; +} +div.codetab { + border-style: solid; + border-width: 0 1px 1px 1px; + border-color:#82c300; + background-color:#ffffff; +} +div.c_tab2 { + border-style: solid; + border-width: 1px 1px 1px 1px; + border-color:#82c300; + background-color:#ffffff; +} +div.topic { + border-style:solid; + border-width:1px; + border-color:#fff273; + background-color:#fff8b2; +} +div.icon-green { + border-style: solid; + border-width: 1px 1px 1px 1px; + border-color: #82c300; +} +div.p-block { + border-style:solid; + border-width:1px; + border-color:#000000; + color:#000000; + background-color:#ffffff; +} +div.clstar-help{ + background-color:#ffffff; + color:#82c300; +} +div.ugo4th{ + border-style:solid; + border-width:1px; + border-color:#c4260f; + background-color:#d52515; +} \ No newline at end of file diff --git a/hatenadir/ds/v2-xx/__ntfts/News.ntft b/hatenadir/ds/v2-xx/__ntfts/News.ntft new file mode 100644 index 0000000..8dadbcf --- /dev/null +++ b/hatenadir/ds/v2-xx/__ntfts/News.ntft @@ -0,0 +1 @@ +’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’ςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςς’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Óςςςς’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Óςςςς’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Óςςςς’Ó’Ó’Ó’Ó’Óςς’Ó’Óςς’Ó’Ó’Ó’Ó’Ó’Óςςςςςςςς’Ó’Ó’Óςςςς’Ó’Ó’Ó’ÓĻ‚’Óςςςς’ÓĻ‚’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Óςςςς’Ó’Ó’Ó’ÓĻ‚’Óςςςς’ÓĻ‚’Ó’Ó’Ó’Ó’Óςςςςςςςς’Ó’Ó’Óςςςς’Ó’Ó’Ó’Óςςςςςςςς’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Óςςςς’Ó’Ó’Óςςςςςςςςςς’Ó’Ó’Ó’Óςςςςςςςς’Ó’Ó’Óςςςς’Ó’Ó’Óςς’Ó’Ó’Ó’Ó’Ó’Óςς’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Óςςςς’Ó’Óςςς’Ó’Ó’Ó’Ó’Ó’Óςςς’Ó’Ó’Óςςςςςςςς’Ó’Ó’Óςςςς’Ó’Óςςςς’Ó’Ó’Ó’Óςςςς’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Óςςςς’Ó’Ó’Óςςςς’Ó’Óςςςς’Ó’Ó’Ó’Óςςςςςςςς’Ó’Ó’Óςςςς’Ó’Óςςςςςςςςςςςς’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Óςςςς’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Óςςςς’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Óςςςς’Ó’Ó’Óςςςςςςςςςςςςςςς’Óςςςςςς’Ó’Ó’Óςςςς’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Óςςςς’Ó’Ó’Óςςςςςς’Óςςςςςςςςςςςςςςς’Ó’Ó’Óςςςς’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Óςςςς’Ó’Ó’Óςςςςςςςςς’Óςςςςςςςςςςςς’Ó’Ó’Óςςςς’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Óςςςς’Ó’Ó’Óςςςςςςςςςςςςςςς’Óςςςςςς’Ó’Ó’Óςςςς’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Óςςςς’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Ó’Óςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςςς’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’ \ No newline at end of file diff --git a/hatenadir/ds/v2-xx/__ntfts/Special Room.ntft b/hatenadir/ds/v2-xx/__ntfts/Special Room.ntft new file mode 100644 index 0000000..cbf8957 --- /dev/null +++ b/hatenadir/ds/v2-xx/__ntfts/Special Room.ntft @@ -0,0 +1 @@ +’’’’’’’’’’’’’’’»ćšŪÜė’’’’’’’’’’’’’’’’’’’’’’’’ŻļyÓ«®Š®Š®Š®Š®Š®ŠŠ–5»»ß’’’’’’’’’’’’’’’’’’ŻļV殊®Š®Š®Š®Š®Š®Š®Š®Š®Š®Š®ŠńžšŪ’’’’’’’’’’’’’’’xĻ®Š®Š®Š®Š®Š®ŠŠŽņšŸń’ŠŽ®Š®Š®Š®Š®Šņ¢Üė’’’’’’’’’’’’5·®Š®Š®Š®Š5£š·žĒ’˒˒˒˒˼æxÆŃ’®Š®Š®ŠÆŠšß’’’’’’’’’’Æ®Š®Š®Šņš»»’Ė’Ė’Ė’Ė’ĖW«®ŠŻĆ’Ė’Ė’Ėy³®Š®Š®Š®Ššß’’’’’’’’VîЮЮŠV§’Ė’Ė’Ė’Ė’Ė’Ė’ĖW«®Šń–š·’Ė’Ė’Ė¼æŠ’®Š®Š®Š¼ė’’’’’’šŪ®Š®Š®ŠW«’Ė’Ė’Ė’Ė’Ė’Ė’Ė’ĖW«®Š®Š®ŠÆŽ6§ŻĆ’ĖŻĆŠ’®Š®ŠŃš’’’’’’Š–®Š®Š4£’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’ĖW«ÆŽ®Š®Š®Š®ŠÆŽy³’ĖÜæ®Š®Š®ŠyÓ’’’’™×®Š®ŠŠ’ŽĒ’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’ĖW«ņš¼æ5£®Š®Š®ŠÆŽŻĆ’˚·®Š®ŠĻ’’’’’ņ¢®Š®Šš·’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’ĖW«ņš’Ė’ĖžĒW«®Š®Š»»’Ė’Ėņ–®Š®Šš×’’Ü뮊®ŠŠŽ’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’ĖW«ņš’Ė’Ė’Ė’Ė5£®ŠŻĆ’˒˚·®Š®Š«’’WîЮŠ5£’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’ĖW«ņš’Ė’Ė’ĖžĒŠ’6§’Ė’Ė’ĖžĒ®Š®Š®Š’’³®Š®Šš·’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’ĖW«ņš’Ė’Ė’ĖŻĆń–’Ė’Ė’Ė’Ė’Ėņ–®Š®Š¼ē’ņ¢®Š®Š¼æ’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’ĖW«ņš’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė4Ÿ®Š®Š™×’њ®Š®ŠŻĆ’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’ĖW«ņš’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė5£®Š®ŠxĻ’њ®Š®ŠŻĆ’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’ĖW«ņš’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė5£®Š®ŠxĻ’ņ¦®Š®Š»»’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’ĖW«ņš’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’ĖŸ®Š®Šš×’5»®Š®ŠxÆ’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’ĖW«ņš’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ėń’®Š®ŠÜė’yӮЮŠ5£’Ė’Ė’Ė’Ė’ĖŻĆxÆŸņš6§»»W«ņš’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’ĖŻĆ®Š®ŠĻ’’’Żļ®Š®ŠÆŠŻĆ’Ė’Ė’Ė6§®Š®Š®Š®Š®Š®ŠŠ’ņš’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’ĖW«®Š®Š5·’’’4·®Š®ŠV§’Ė’Ė¼æ®Š®Š®Š®Š®Š®Š®Š®Šņš’Ė’Ė’Ė’Ė’Ė’Ė’Ė’ĖŻĆÆŠ®Š®Š»ć’’’»ć®Š®Š®Š¼æ’Ė»»®Š®Š®Š®Š®Š®Š®Š®Šņš’Ė’Ė’Ė’Ė’Ė’Ė’Ė’ĖV§®Š®Šņ¦’’’’’³®Š®ŠŠ’ŽĆ’Ėń–®Š®Š®Š®Š®Š®ŠÆŽ¼æ’Ė’Ė’Ė’Ė’Ė’Ė’Ė™³®Š®Š®Š»ć’’’’’¼ė®Š®Š®Š›ŽĆ’Ėy³W«ņšņš6§y³žĒ’Ė’Ė’Ė’Ė’Ė’Ė’Ė»»®Š®Š®Š4³’’’’’’’šß®Š®Š®Šń’Żæ’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’ĖxÆ®Š®Š®Šńž’’’’’’’’’xϮЮЮЮŠw«žĒ’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė’Ė»»Ÿ®Š®Š®ŠŠ’Żļ’’’’’’’’’’š×®Š®Š®Š®ŠŠŽ5£š·ŻĆŽĆžĒŽĆ»»xÆ›®Š®Š®Š®Šņ¦’’’’’’’’’’’’’¼ė«®Š®Š®Š®Š®Š®Š®Š®Š®Š®Š®Š®Š®Š®Š®ŠWĒ’’’’’’’’’’’’’’’’»ßÆ®Š®Š®Š®Š®Š®Š®Š®Š®Š®ŠÆŽVæÜė’’’’’’’’’’’’’’’’’’’ÜėxĻÆŃšŠ’Ļ’Š’ņ¢5»»ß’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’ \ No newline at end of file diff --git a/hatenadir/ds/v2-xx/de/confirm/delete.txt b/hatenadir/ds/v2-xx/de/confirm/delete.txt new file mode 100644 index 0000000..f53d3fa Binary files /dev/null and b/hatenadir/ds/v2-xx/de/confirm/delete.txt differ diff --git a/hatenadir/ds/v2-xx/de/confirm/download.txt b/hatenadir/ds/v2-xx/de/confirm/download.txt new file mode 100644 index 0000000..9850b6a Binary files /dev/null and b/hatenadir/ds/v2-xx/de/confirm/download.txt differ diff --git a/hatenadir/ds/v2-xx/de/confirm/upload.txt b/hatenadir/ds/v2-xx/de/confirm/upload.txt new file mode 100644 index 0000000..96a3d1a Binary files /dev/null and b/hatenadir/ds/v2-xx/de/confirm/upload.txt differ diff --git a/hatenadir/ds/v2-xx/de/eula.txt b/hatenadir/ds/v2-xx/de/eula.txt new file mode 100644 index 0000000..afde044 Binary files /dev/null and b/hatenadir/ds/v2-xx/de/eula.txt differ diff --git a/hatenadir/ds/v2-xx/en/confirm/delete.txt b/hatenadir/ds/v2-xx/en/confirm/delete.txt new file mode 100644 index 0000000..f53d3fa Binary files /dev/null and b/hatenadir/ds/v2-xx/en/confirm/delete.txt differ diff --git a/hatenadir/ds/v2-xx/en/confirm/download.txt b/hatenadir/ds/v2-xx/en/confirm/download.txt new file mode 100644 index 0000000..9850b6a Binary files /dev/null and b/hatenadir/ds/v2-xx/en/confirm/download.txt differ diff --git a/hatenadir/ds/v2-xx/en/confirm/upload.txt b/hatenadir/ds/v2-xx/en/confirm/upload.txt new file mode 100644 index 0000000..96a3d1a Binary files /dev/null and b/hatenadir/ds/v2-xx/en/confirm/upload.txt differ diff --git a/hatenadir/ds/v2-xx/en/eula.txt b/hatenadir/ds/v2-xx/en/eula.txt new file mode 100644 index 0000000..afde044 Binary files /dev/null and b/hatenadir/ds/v2-xx/en/eula.txt differ diff --git a/hatenadir/ds/v2-xx/es/confirm/delete.txt b/hatenadir/ds/v2-xx/es/confirm/delete.txt new file mode 100644 index 0000000..f53d3fa Binary files /dev/null and b/hatenadir/ds/v2-xx/es/confirm/delete.txt differ diff --git a/hatenadir/ds/v2-xx/es/confirm/download.txt b/hatenadir/ds/v2-xx/es/confirm/download.txt new file mode 100644 index 0000000..9850b6a Binary files /dev/null and b/hatenadir/ds/v2-xx/es/confirm/download.txt differ diff --git a/hatenadir/ds/v2-xx/es/confirm/upload.txt b/hatenadir/ds/v2-xx/es/confirm/upload.txt new file mode 100644 index 0000000..96a3d1a Binary files /dev/null and b/hatenadir/ds/v2-xx/es/confirm/upload.txt differ diff --git a/hatenadir/ds/v2-xx/es/eula.txt b/hatenadir/ds/v2-xx/es/eula.txt new file mode 100644 index 0000000..afde044 Binary files /dev/null and b/hatenadir/ds/v2-xx/es/eula.txt differ diff --git a/hatenadir/ds/v2-xx/eula_list.tsv b/hatenadir/ds/v2-xx/eula_list.tsv new file mode 100644 index 0000000..63798b1 --- /dev/null +++ b/hatenadir/ds/v2-xx/eula_list.tsv @@ -0,0 +1 @@ +RQBuAGcAbABpAHMAaAA= en diff --git a/hatenadir/ds/v2-xx/fr/confirm/delete.txt b/hatenadir/ds/v2-xx/fr/confirm/delete.txt new file mode 100644 index 0000000..f53d3fa Binary files /dev/null and b/hatenadir/ds/v2-xx/fr/confirm/delete.txt differ diff --git a/hatenadir/ds/v2-xx/fr/confirm/download.txt b/hatenadir/ds/v2-xx/fr/confirm/download.txt new file mode 100644 index 0000000..9850b6a Binary files /dev/null and b/hatenadir/ds/v2-xx/fr/confirm/download.txt differ diff --git a/hatenadir/ds/v2-xx/fr/confirm/upload.txt b/hatenadir/ds/v2-xx/fr/confirm/upload.txt new file mode 100644 index 0000000..96a3d1a Binary files /dev/null and b/hatenadir/ds/v2-xx/fr/confirm/upload.txt differ diff --git a/hatenadir/ds/v2-xx/fr/eula.txt b/hatenadir/ds/v2-xx/fr/eula.txt new file mode 100644 index 0000000..afde044 Binary files /dev/null and b/hatenadir/ds/v2-xx/fr/eula.txt differ diff --git a/hatenadir/ds/v2-xx/frontpage/hotmovies.ugo.py b/hatenadir/ds/v2-xx/frontpage/hotmovies.ugo.py new file mode 100644 index 0000000..2f98138 --- /dev/null +++ b/hatenadir/ds/v2-xx/frontpage/hotmovies.ugo.py @@ -0,0 +1,73 @@ +from twisted.web import resource +from twisted.internet import reactor +import time + +from hatena import Log, NotFound, request_args, request_path +from DB import Database +from Hatenatools import UGO + + +class PyResource(resource.Resource): + isLeaf = True + + def __init__(self): + super().__init__() + self.pages = [] + self.newestflip = None + self.newestview = None + self.Update() + + def render(self, request): + try: + page = int(request_args(request).get("page", ["1"])[0]) + except ValueError: + page = 1 + if 1 <= page <= len(self.pages): + path = "/".join(request_path(request).split("/")[3:]) + Log(request, "%s page %i" % (path, page)) + request.setHeader(b"content-type", b"text/plain") + return self.pages[page - 1] + return NotFound.render(request) + + def Update(self): + reactor.callLater(600, self.Update) + current = Database.Newest[0] if Database.Newest else None + if current != self.newestflip or self.newestview != Database.Views: + self.newestflip = current + self.newestview = Database.Views + reactor.callInThread(self.UpdateThreaded, list(Database.Newest)) + + def UpdateThreaded(self, flipnotes): + def score(item): + i, (creator_id, flip) = item + views, stars = Database.GetFlipnote(creator_id, flip)[1:3] + return int(views) * 60 + int(stars) // 4 - i + flipnotes = [x[1] for x in sorted(enumerate(flipnotes), key=score, reverse=True)[:500]] + pages = [] + pagecount = (len(flipnotes) + 49) // 50 + pagecount = min(pagecount, 10) + flipcount = min(len(flipnotes), 500) + for i in range(pagecount): + pages.append(self.MakePage(flipnotes[i * 50 : i * 50 + 50], i + 1, i < pagecount - 1, flipcount)) + if self.pages: + print(time.strftime("[%H:%M:%S] Updated hotmovies.ugo")) + self.pages = pages + + def MakePage(self, flipnotes, page, has_next, count): + ugo = UGO() + ugo.Loaded = True + ugo.Items = [] + ugo.Items.append(("layout", (2, 1))) + ugo.Items.append(("topscreen text", ["Popular Flipnotes", "Flipnotes", str(count), "", "The most popular new Flipnotes."], 0)) + ugo.Items.append(("category", "http://flipnote.hatena.com/ds/v2-xx/frontpage/hotmovies.uls", "Most Popular", True)) + ugo.Items.append(("category", "http://flipnote.hatena.com/ds/v2-xx/frontpage/likedmovies.uls", "Most Liked", False)) + ugo.Items.append(("category", "http://flipnote.hatena.com/ds/v2-xx/frontpage/newmovies.uls", "New Flipnotes", False)) + ugo.Items.append(("unknown", ("3", "http://flipnote.hatena.com/ds/v2-xx/help/post_howto.htm", "UABvAHMAdAAgAEYAbABpAHAAbgBvAHQAZQA="))) + if page > 1: + ugo.Items.append(("button", 115, "Previous", "http://flipnote.hatena.com/ds/v2-xx/frontpage/hotmovies.uls?page=%i" % (page - 1), ("", ""), None)) + for creatorid, filename in flipnotes: + stars = str(Database.GetFlipnote(creatorid, filename)[2]) + ugo.Items.append(("button", 3, "", "http://flipnote.hatena.com/ds/v2-xx/movie/%s/%s.ppm" % (creatorid, filename), (stars, "765", "573", "0"), (filename + ".ppm", Database.GetFlipnoteTMB(creatorid, filename)))) + if has_next: + ugo.Items.append(("button", 115, "Next", "http://flipnote.hatena.com/ds/v2-xx/frontpage/hotmovies.uls?page=%i" % (page + 1), ("", ""), None)) + return ugo.Pack() diff --git a/hatenadir/ds/v2-xx/frontpage/likedmovies.ugo.py b/hatenadir/ds/v2-xx/frontpage/likedmovies.ugo.py new file mode 100644 index 0000000..4ee9df4 --- /dev/null +++ b/hatenadir/ds/v2-xx/frontpage/likedmovies.ugo.py @@ -0,0 +1,73 @@ +from twisted.web import resource +from twisted.internet import reactor +import time + +from hatena import Log, NotFound, request_args, request_path +from DB import Database +from Hatenatools import UGO + + +class PyResource(resource.Resource): + isLeaf = True + + def __init__(self): + super().__init__() + self.pages = [] + self.newestflip = None + self.neweststar = None + reactor.callLater(2, self.Update) + + def render(self, request): + try: + page = int(request_args(request).get("page", ["1"])[0]) + except ValueError: + page = 1 + if 1 <= page <= len(self.pages): + path = "/".join(request_path(request).split("/")[3:]) + Log(request, "%s page %i" % (path, page)) + request.setHeader(b"content-type", b"text/plain") + return self.pages[page - 1] + return NotFound.render(request) + + def Update(self): + reactor.callLater(600, self.Update) + current = Database.Newest[0] if Database.Newest else None + if current != self.newestflip or self.neweststar != Database.Stars: + self.newestflip = current + self.neweststar = Database.Stars + reactor.callInThread(self.UpdateThreaded, list(Database.Newest)) + + def UpdateThreaded(self, flipnotes): + def score(item): + i, (creator_id, flip) = item + views, stars = Database.GetFlipnote(creator_id, flip)[1:3] + return int(stars) * 110 + int(views) // 10 - i + flipnotes = [x[1] for x in sorted(enumerate(flipnotes), key=score, reverse=True)[:500]] + pages = [] + pagecount = (len(flipnotes) + 49) // 50 + pagecount = min(pagecount, 10) + flipcount = min(len(flipnotes), 500) + for i in range(pagecount): + pages.append(self.MakePage(flipnotes[i * 50 : i * 50 + 50], i + 1, i < pagecount - 1, flipcount)) + if self.pages: + print(time.strftime("[%H:%M:%S] Updated likedmovies.ugo")) + self.pages = pages + + def MakePage(self, flipnotes, page, has_next, count): + ugo = UGO() + ugo.Loaded = True + ugo.Items = [] + ugo.Items.append(("layout", (2, 1))) + ugo.Items.append(("topscreen text", ["Liked Flipnotes", "Flipnotes", str(count), "", "The most liked new Flipnotes."], 0)) + ugo.Items.append(("category", "http://flipnote.hatena.com/ds/v2-xx/frontpage/hotmovies.uls", "Most Popular", False)) + ugo.Items.append(("category", "http://flipnote.hatena.com/ds/v2-xx/frontpage/likedmovies.uls", "Most Liked", True)) + ugo.Items.append(("category", "http://flipnote.hatena.com/ds/v2-xx/frontpage/newmovies.uls", "New Flipnotes", False)) + ugo.Items.append(("unknown", ("3", "http://flipnote.hatena.com/ds/v2-xx/help/post_howto.htm", "UABvAHMAdAAgAEYAbABpAHAAbgBvAHQAZQA="))) + if page > 1: + ugo.Items.append(("button", 115, "Previous", "http://flipnote.hatena.com/ds/v2-xx/frontpage/likedmovies.uls?page=%i" % (page - 1), ("", ""), None)) + for creatorid, filename in flipnotes: + stars = str(Database.GetFlipnote(creatorid, filename)[2]) + ugo.Items.append(("button", 3, "", "http://flipnote.hatena.com/ds/v2-xx/movie/%s/%s.ppm" % (creatorid, filename), (stars, "765", "573", "0"), (filename + ".ppm", Database.GetFlipnoteTMB(creatorid, filename)))) + if has_next: + ugo.Items.append(("button", 115, "Next", "http://flipnote.hatena.com/ds/v2-xx/frontpage/likedmovies.uls?page=%i" % (page + 1), ("", ""), None)) + return ugo.Pack() diff --git a/hatenadir/ds/v2-xx/frontpage/newmovies.ugo.py b/hatenadir/ds/v2-xx/frontpage/newmovies.ugo.py new file mode 100644 index 0000000..84a0910 --- /dev/null +++ b/hatenadir/ds/v2-xx/frontpage/newmovies.ugo.py @@ -0,0 +1,67 @@ +from twisted.web import resource +from twisted.internet import reactor +import time + +from hatena import Log, NotFound, request_args, request_path +from DB import Database +from Hatenatools import UGO + + +class PyResource(resource.Resource): + isLeaf = True + + def __init__(self): + super().__init__() + self.pages = [] + self.newestflip = None + reactor.callLater(4, self.Update) + + def render(self, request): + try: + page = int(request_args(request).get("page", ["1"])[0]) + except ValueError: + page = 1 + if 1 <= page <= len(self.pages): + path = "/".join(request_path(request).split("/")[3:]) + Log(request, "%s page %i" % (path, page)) + request.setHeader(b"content-type", b"text/plain") + return self.pages[page - 1] + return NotFound.render(request) + + def Update(self): + reactor.callLater(60, self.Update) + current = Database.Newest[0] if Database.Newest else None + if current != self.newestflip: + self.newestflip = current + reactor.callInThread(self.UpdateThreaded, list(Database.Newest)) + + def UpdateThreaded(self, flipnotes): + flipnotes = list(flipnotes) + pages = [] + pagecount = (len(flipnotes) + 49) // 50 + pagecount = min(pagecount, 10) + flipcount = len(flipnotes) + for i in range(pagecount): + pages.append(self.MakePage(flipnotes[i * 50 : i * 50 + 50], i + 1, i < pagecount - 1, flipcount)) + if self.pages: + print(time.strftime("[%H:%M:%S] Updated newmovies.ugo")) + self.pages = pages + + def MakePage(self, flipnotes, page, has_next, count): + ugo = UGO() + ugo.Loaded = True + ugo.Items = [] + ugo.Items.append(("layout", (2, 1))) + ugo.Items.append(("topscreen text", ["New Flipnotes", "Flipnotes", str(count), "", "The newest Flipnotes submitted."], 0)) + ugo.Items.append(("category", "http://flipnote.hatena.com/ds/v2-xx/frontpage/hotmovies.uls", "Most Popular", False)) + ugo.Items.append(("category", "http://flipnote.hatena.com/ds/v2-xx/frontpage/likedmovies.uls", "Most Liked", False)) + ugo.Items.append(("category", "http://flipnote.hatena.com/ds/v2-xx/frontpage/newmovies.uls", "New Flipnotes", True)) + ugo.Items.append(("unknown", ("3", "http://flipnote.hatena.com/ds/v2-xx/help/post_howto.htm", "UABvAHMAdAAgAEYAbABpAHAAbgBvAHQAZQA="))) + if page > 1: + ugo.Items.append(("button", 115, "Previous", "http://flipnote.hatena.com/ds/v2-xx/frontpage/newmovies.uls?page=%i" % (page - 1), ("", ""), None)) + for creatorid, filename in flipnotes: + stars = str(Database.GetFlipnote(creatorid, filename)[2]) + ugo.Items.append(("button", 3, "", "http://flipnote.hatena.com/ds/v2-xx/movie/%s/%s.ppm" % (creatorid, filename), (stars, "765", "573", "0"), (filename + ".ppm", Database.GetFlipnoteTMB(creatorid, filename)))) + if has_next: + ugo.Items.append(("button", 115, "Next", "http://flipnote.hatena.com/ds/v2-xx/frontpage/newmovies.uls?page=%i" % (page + 1), ("", ""), None)) + return ugo.Pack() diff --git a/hatenadir/ds/v2-xx/help/info.htm b/hatenadir/ds/v2-xx/help/info.htm new file mode 100644 index 0000000..5cded24 --- /dev/null +++ b/hatenadir/ds/v2-xx/help/info.htm @@ -0,0 +1 @@ + Info
pbsds's Hatena Server

This server is a proof of concept server. There's not much functionality yet because it's in early stages. Please enjoy your stay.

\ No newline at end of file diff --git a/hatenadir/ds/v2-xx/help/post_howto.htm b/hatenadir/ds/v2-xx/help/post_howto.htm new file mode 100644 index 0000000..acaf5b2 --- /dev/null +++ b/hatenadir/ds/v2-xx/help/post_howto.htm @@ -0,0 +1 @@ + Post Flipnote
Posting a Flipnote

Posting a flipnote is as easy as pressing the button down below and selecting the flipnote you want to upload!

\ No newline at end of file diff --git a/hatenadir/ds/v2-xx/inbox.ugoxml b/hatenadir/ds/v2-xx/inbox.ugoxml new file mode 100644 index 0000000..76b19e1 --- /dev/null +++ b/hatenadir/ds/v2-xx/inbox.ugoxml @@ -0,0 +1,20 @@ + + + + 2 + 1 + + + <label>Inbox</label> + <label /> + <label /> + <label /> + <label /> + <num>0</num> + + + diff --git a/hatenadir/ds/v2-xx/index.ugoxml b/hatenadir/ds/v2-xx/index.ugoxml new file mode 100644 index 0000000..348465a --- /dev/null +++ b/hatenadir/ds/v2-xx/index.ugoxml @@ -0,0 +1,29 @@ + + + + 0 + + + <label /> + <label /> + <label /> + <label /> + <label /> + <num>0</num> + + + + diff --git a/hatenadir/ds/v2-xx/it/confirm/delete.txt b/hatenadir/ds/v2-xx/it/confirm/delete.txt new file mode 100644 index 0000000..f53d3fa Binary files /dev/null and b/hatenadir/ds/v2-xx/it/confirm/delete.txt differ diff --git a/hatenadir/ds/v2-xx/it/confirm/download.txt b/hatenadir/ds/v2-xx/it/confirm/download.txt new file mode 100644 index 0000000..9850b6a Binary files /dev/null and b/hatenadir/ds/v2-xx/it/confirm/download.txt differ diff --git a/hatenadir/ds/v2-xx/it/confirm/upload.txt b/hatenadir/ds/v2-xx/it/confirm/upload.txt new file mode 100644 index 0000000..96a3d1a Binary files /dev/null and b/hatenadir/ds/v2-xx/it/confirm/upload.txt differ diff --git a/hatenadir/ds/v2-xx/it/eula.txt b/hatenadir/ds/v2-xx/it/eula.txt new file mode 100644 index 0000000..afde044 Binary files /dev/null and b/hatenadir/ds/v2-xx/it/eula.txt differ diff --git a/hatenadir/ds/v2-xx/movie.py b/hatenadir/ds/v2-xx/movie.py new file mode 100644 index 0000000..c4c98cd --- /dev/null +++ b/hatenadir/ds/v2-xx/movie.py @@ -0,0 +1,221 @@ +from twisted.web import resource + +from hatena import Log, ServerLog, Silent, NotFound, as_text, request_path, request_args, request_headers, client_ip +from DB import Database +from Hatenatools import TMB + + +class PyResource(resource.Resource): + isLeaf = False + + def __init__(self): + super().__init__() + self.CreatorID = CreatorIDResource() + + def getChild(self, name, request): + name = as_text(name) + if Database.CreatorExists(name): + return self.CreatorID + if name == "": + return self + return NotFound + + def render(self, request): + request.setResponseCode(403) + return b"403 - Denied access" + + +class CreatorIDResource(resource.Resource): + isLeaf = False + + def __init__(self): + super().__init__() + self.CreatorIDFile = CreatorIDFileResource() + + def getChild(self, name, request): + creator_id = request_path(request).split("/")[-2] + name = as_text(name) + filename = ".".join(name.split(".")[:-1]) + if Database.FlipnoteExists(creator_id, filename): + return self.CreatorIDFile + if name == "": + return self + return NotFound + + def render(self, request): + request.setResponseCode(403) + return b"403 - Denied access" + + +class CreatorIDFileResource(resource.Resource): + isLeaf = True + + def render(self, request): + creator, file = request_path(request).split("/")[-2:] + filetype = file.rsplit(".", 1)[-1].lower() + path = "/".join(request_path(request).split("/")[3:]) + + if filetype == "ppm": + Log(request, path) + Database.AddView(creator, file[:-4]) + request.setHeader(b"content-type", b"text/plain") + return Database.GetFlipnotePPM(creator, file[:-4]) + + if filetype == "info": + Log(request, path, True) + request.setHeader(b"content-type", b"text/plain") + return b"0\n0\n" + + if filetype == "htm": + request.setHeader(b"content-type", b"text/html; charset=utf-8") + return self.GenerateDetailsPage(creator, ".".join(file.split(".")[:-1])).encode("UTF-8") + + if filetype == "star": + args = request_args(request) + color = args.get("starcolor", ["yellow"])[0].split(",", 1)[0].lower() + headers = request_headers(request) + if "x-hatena-star-count" not in headers: + ServerLog.write( + "%s got 403 when requesting %s without a X-Hatena-Star-Count header" % (client_ip(request), path), + Silent, + ) + request.setResponseCode(403) + return b"403 - Denied access\nRequest lacks a X-Hatena-Star-Count http header" + try: + amount = int(headers["x-hatena-star-count"]) + except ValueError: + amount = 0 + if amount < 1 or amount > 65535: + ServerLog.write( + "%s got 403 when requesting %s with an invalid X-Hatena-Star-Count header" % (client_ip(request), path), + Silent, + ) + request.setResponseCode(403) + return b"403 - Denied access\nRequest has an invalid X-Hatena-Star-Count http header" + if not Database.AddStar(creator, file[:-5], amount, color): + ServerLog.write("%s got 500 when requesting %s" % (client_ip(request), path), Silent) + request.setResponseCode(500) + return b"500 - Internal server error\nAdding the stars seems to have failed." + ServerLog.write( + "%s added %i %s stars to %s/%s.ppm" % (client_ip(request), amount, color, creator, file[:-5]), + Silent, + ) + return b"Success" + + if filetype == "dl": + Log(request, path, True) + Database.AddDownload(creator, file[:-3]) + return b"Noted ;)" + + ServerLog.write("%s got 403 when requesting %s" % (client_ip(request), path), Silent) + request.setResponseCode(403) + return b"403 - Denied access" + + def GenerateDetailsPage(self, CreatorID, filename): + flipnote = Database.GetFlipnote(CreatorID, filename) + if not flipnote: + return "This flipnote doesn't exist!" + tmb = TMB().Read(Database.GetFlipnoteTMB(CreatorID, filename)) + if not tmb: + return "This flipnote is corrupt!" + + spinoff = "" + if tmb.OriginalAuthorID != tmb.EditorAuthorID or tmb.OriginalFilename != tmb.CurrentFilename: + if Database.FlipnoteExists(tmb.OriginalAuthorID, tmb.OriginalFilename[:-4]): + spinoff = SpinoffTemplate1.replace("%%CreatorID%%", tmb.OriginalAuthorID).replace("%%Filename%%", tmb.OriginalFilename[:-4]) + elif tmb.OriginalAuthorID != tmb.EditorAuthorID: + spinoff = SpinoffTemplate2 + + entries = [] + content = '%s' % (CreatorID, tmb.Username) + entries.append(PageEntryTemplate.replace("%%Name%%", "Creator").replace("%%Content%%", content)) + + content = 'ā˜… %s' % (CreatorID, filename, flipnote[2]) + for css, value in zip(("1", "2", "3", "4"), flipnote[3:7]): + content += '
ā˜… %s' % (CreatorID, filename, css, css, value) + entries.append(PageEntryTemplate.replace("%%Name%%", "Stars").replace("%%Content%%", content)) + entries.append(PageEntryTemplate.replace("%%Name%%", "Views").replace("%%Content%%", str(flipnote[1]))) + entries.append(PageEntryTemplate.replace("%%Name%%", "Downloads").replace("%%Content%%", str(flipnote[8]))) + + if flipnote[7]: + content = '%s' % (flipnote[7], flipnote[7]) + entries.append(PageEntryTemplate.replace("%%Name%%", "Channel").replace("%%Content%%", content)) + + return ( + DetailsPageTemplate.replace("%%CreatorID%%", CreatorID) + .replace("%%Filename%%", filename) + .replace("%%Username%%", tmb.Username) + .replace("%%CommentCount%%", "0") + .replace("%%Spinoff%%", spinoff) + .replace("%%PageEntries%%", PageEntrySeparator.join(entries)) + ) + +#templates: +DetailsPageTemplate = """ + + Flipnote by %%Username%% + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+
+
+
Description
+
+ Comments(%%CommentCount%%) +
+
%%Spinoff%% + %%PageEntries%% +
+ +""" +SpinoffTemplate1 = """ +
+ This Flipnote is a spin-off.
+ Original Flipnote +
""" +SpinoffTemplate2 = """ +
+ This Flipnote is a spin-off. +
""" +PageEntryTemplate = """ + + +
%%Name%%
+ + +
+ %%Content%% +
+ + """ +PageEntrySeparator=""" + + + +
+ + """ diff --git a/hatenadir/ds/v2-xx/post/flipnote.post.py b/hatenadir/ds/v2-xx/post/flipnote.post.py new file mode 100644 index 0000000..5a4c104 --- /dev/null +++ b/hatenadir/ds/v2-xx/post/flipnote.post.py @@ -0,0 +1,25 @@ +from twisted.web import resource + +from hatena import ServerLog, Silent, request_args, client_ip +from DB import Database + + +class PyResource(resource.Resource): + isLeaf = True + + def render_GET(self, request): + ServerLog.write("%s got 403 when requesting post/flipnote.post with GET" % client_ip(request), Silent) + request.setResponseCode(405) + return b"405 - Method Not Allowed" + + def render_POST(self, request): + data = request.content.read() + channel = request_args(request).get("channel", [""])[0] + add = Database.AddFlipnote(data, channel) + if add: + ServerLog.write('%s successfully uploaded "%s.ppm"' % (client_ip(request), add[1]), Silent) + request.setResponseCode(200) + else: + ServerLog.write("%s tried to upload a flipnote, but failed..." % client_ip(request), Silent) + request.setResponseCode(500) + return b"" diff --git a/hatenadir/images/ds/kaeru.ntft b/hatenadir/images/ds/kaeru.ntft new file mode 100644 index 0000000..7032be8 --- /dev/null +++ b/hatenadir/images/ds/kaeru.ntft @@ -0,0 +1 @@ +’’’’’’’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’3ƒ3ƒ3ƒ’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’3ƒ3ƒ3ƒ’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’3ƒ3ƒ3ƒ’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’3ƒ3ƒ3ƒ’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’3ƒ3ƒ3ƒ’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’3ƒ3ƒ3ƒ’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’3ƒ3ƒ3ƒ’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’3ƒ3ƒ3ƒ’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’3ƒ3ƒ3ƒ’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’3ƒ3ƒ3ƒ’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’3ƒ3ƒ3ƒ’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’3ƒ3ƒ3ƒ’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’’’’’’’’’’’’’’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’’’’’’’’’’’’’’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’’’’’’’’’’’’’’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’’’’’’’’’’’’’’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’’’’’’’’’’’’’’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’’’’’’’’’’’’’’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’’’’’’’’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’’’’’’’’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’’’’’’’’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ3ƒ \ No newline at end of file diff --git a/hatenadir/images/ds/list.ntft b/hatenadir/images/ds/list.ntft new file mode 100644 index 0000000..9fb2b0d --- /dev/null +++ b/hatenadir/images/ds/list.ntft @@ -0,0 +1 @@ +’’’’’’’’’’’’’’’’’’2ƒ2ƒ2ƒ2ƒ’’’2ƒ2ƒ2ƒ2ƒ2ƒ2ƒ’2ƒ2ƒ2ƒ’’2ƒ2ƒ2ƒ2ƒ2ƒ’’’’2ƒ2ƒ2ƒ2ƒ’’’’2ƒ2ƒ2ƒ2ƒ2ƒ’’2ƒ2ƒ2ƒ’2ƒ2ƒ2ƒ2ƒ2ƒ2ƒ’’’2ƒ2ƒ2ƒ2ƒ’’’’2ƒ2ƒ2ƒ2ƒ’’’’2ƒ2ƒ2ƒ2ƒ’’’’2ƒ2ƒ2ƒ2ƒ’’’’2ƒ2ƒ2ƒ2ƒ’’’’2ƒ2ƒ2ƒ2ƒ’’’’2ƒ2ƒ2ƒ2ƒ’’ \ No newline at end of file diff --git a/hatenadir/images/ds/theme/basic/background.nbf b/hatenadir/images/ds/theme/basic/background.nbf new file mode 100644 index 0000000..dc7f3b6 Binary files /dev/null and b/hatenadir/images/ds/theme/basic/background.nbf differ diff --git a/hatenadir/images/ds/theme/basic/foot.ntft b/hatenadir/images/ds/theme/basic/foot.ntft new file mode 100644 index 0000000..659a896 --- /dev/null +++ b/hatenadir/images/ds/theme/basic/foot.ntft @@ -0,0 +1 @@ +ƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒ’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’ƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒ’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’ƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒ’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’ƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒ’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’ƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒ’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’ \ No newline at end of file diff --git a/hatenadir/images/ds/theme/basic/head.ntft b/hatenadir/images/ds/theme/basic/head.ntft new file mode 100644 index 0000000..3e4f3fa --- /dev/null +++ b/hatenadir/images/ds/theme/basic/head.ntft @@ -0,0 +1 @@ +’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’ƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒ \ No newline at end of file diff --git a/hatenadir/images/ds/thumb_down.ntft b/hatenadir/images/ds/thumb_down.ntft new file mode 100644 index 0000000..d9c7b21 --- /dev/null +++ b/hatenadir/images/ds/thumb_down.ntft @@ -0,0 +1 @@ +’’’™55555555’’’’’’™Ÿć?Ļüü?Ļ?Ļ?Ļ?Ļ?Ļ55’’’’™Ÿć?Ļ?Ļ?Ļü?ϟćŸć?Ļ?Ļ?Ļ5’’’üüüüü?Ļ?ϟćŸćŸćŸćŸć?Ļ5’’™Ÿć?Ļ?Ļ?Ļü?Ļ?Ļ?Ļ?Ļ?ϟćŸć5’’üüüüü?Ļ?Ļüüü?ϟćŸć™’’™Ÿć?Ļ?Ļ?Ļüü?Ļ?Ļ?Ļ?ϟćŸć™’’üüüüü?Ļ?Ļ?ϟćŸćŸć?Ļ?Ļ5’’™ŸćŸćŸćŸćü?ϟćŸćŸć?Ļ?Ļ5’’’’™™™™5?Ļ?Ļ?Ļ?Ļ55’’’’’’’’’5?Ļ?Ļ?Ļ5’’’’’’’’’’™?Ļ?Ļ?Ļ5’’’’’’’’’’™Ÿć?Ļ?Ļ5’’’’’’’’’’’™Ÿć?Ļ?Ļ5’’’’’’’’’’’™ŸćŸćŸć™’’’’’’’’’’’’™™™’’’’’’’ \ No newline at end of file diff --git a/tests/test_database.py b/tests/test_database.py new file mode 100644 index 0000000..b9a104e --- /dev/null +++ b/tests/test_database.py @@ -0,0 +1,59 @@ +from __future__ import annotations + +import os +import shutil +import tempfile +import unittest +from pathlib import Path + +import database as database_module + + +ROOT = Path(__file__).resolve().parents[1] +SAMPLE_CREATOR = "913304C0CC74CC1F" +SAMPLE_NAME = "74CC1F_0D3AA40F2B3A0_000" + + +class DatabaseTests(unittest.TestCase): + def setUp(self): + self.tmp = tempfile.TemporaryDirectory() + self.old_cwd = os.getcwd() + temp_root = Path(self.tmp.name) + shutil.copytree(ROOT / "database", temp_root / "database") + os.chdir(temp_root) + self.db = database_module.Database.__class__() + + def tearDown(self): + # Prevent the per-test instance from having anything left to flush at interpreter exit. + self.db.Creator.clear() + self.db.new = False + os.chdir(self.old_cwd) + self.tmp.cleanup() + + def test_read_sample(self): + self.assertTrue(self.db.CreatorExists(SAMPLE_CREATOR)) + row = self.db.GetFlipnote(SAMPLE_CREATOR, SAMPLE_NAME) + self.assertTrue(row) + self.assertEqual(row[0], SAMPLE_NAME) + self.assertEqual(len(row), 9) + self.assertTrue(self.db.GetFlipnotePPM(SAMPLE_CREATOR, SAMPLE_NAME).startswith(b"PARA")) + self.assertEqual(len(self.db.GetFlipnoteTMB(SAMPLE_CREATOR, SAMPLE_NAME)), 0x6A0) + + def test_counters_and_write(self): + self.assertTrue(self.db.AddView(SAMPLE_CREATOR, SAMPLE_NAME)) + self.assertTrue(self.db.AddStar(SAMPLE_CREATOR, SAMPLE_NAME, 5, "green")) + self.assertTrue(self.db.AddDownload(SAMPLE_CREATOR, SAMPLE_NAME)) + self.assertEqual(self.db.Views, 1) + self.assertEqual(self.db.Stars, 1) + self.assertEqual(self.db.Downloads, 1) + row = self.db.GetFlipnote(SAMPLE_CREATOR, SAMPLE_NAME, True) + self.assertEqual(int(row[1]), 3) + self.assertEqual(int(row[3]), 5) + self.assertEqual(int(row[8]), 1) + self.db.write() + text = Path("database/Creators") / SAMPLE_CREATOR / "flipnotes.dat" + self.assertIn("\t3\t", text.read_text(encoding="utf-8")) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_formats.py b/tests/test_formats.py new file mode 100644 index 0000000..05008ed --- /dev/null +++ b/tests/test_formats.py @@ -0,0 +1,98 @@ +from __future__ import annotations + +import os +import tempfile +import unittest +from pathlib import Path + +import numpy as np + +from Hatenatools import NTFT, PPM, TMB, UGO +from Hatenatools.PPM import WriteImage, get_metadata + + +ROOT = Path(__file__).resolve().parents[1] +SAMPLE_PPM = ROOT / "database" / "Creators" / "913304C0CC74CC1F" / "74CC1F_0D3AA40F2B3A0_000.ppm" +NEWS_NTFT = ROOT / "hatenadir" / "ds" / "v2-xx" / "__ntfts" / "News.ntft" +KAERU_NTFT = ROOT / "hatenadir" / "images" / "ds" / "kaeru.ntft" +INDEX_UGOXML = ROOT / "hatenadir" / "ds" / "v2-xx" / "index.ugoxml" +INBOX_UGOXML = ROOT / "hatenadir" / "ds" / "v2-xx" / "inbox.ugoxml" + + +class PPMTests(unittest.TestCase): + @classmethod + def setUpClass(cls): + cls.data = SAMPLE_PPM.read_bytes() + + def test_tmb_metadata_and_exact_pack(self): + tmb = TMB().Read(self.data[:0x6A0], DecodeThumbnail=True) + self.assertTrue(tmb) + self.assertEqual(tmb.EditorAuthorID, "913304C0CC74CC1F") + self.assertEqual(tmb.CurrentFilename, "74CC1F_0D3AA40F2B3A0_000.tmb") + self.assertEqual(tmb.FrameCount, 3) + self.assertEqual(tmb.GetThumbnail().shape, (64, 48)) + self.assertEqual(tmb.Pack(), self.data[:0x6A0]) + + def test_ppm_full_parse_and_frame(self): + ppm = PPM().Read(self.data, DecodeThumbnail=True, ReadFrames=True, ReadSound=True) + self.assertTrue(ppm) + self.assertEqual(ppm.EditorAuthorID, "913304C0CC74CC1F") + self.assertEqual(ppm.CurrentFilename, "74CC1F_0D3AA40F2B3A0_000.ppm") + self.assertEqual(ppm.FrameCount, 3) + self.assertEqual(ppm.GetThumbnail().shape, (64, 48)) + frame = ppm.GetFrame(0) + self.assertIsInstance(frame, np.ndarray) + self.assertEqual(frame.shape, (256, 192)) + self.assertEqual(len(ppm.SoundData), 4) + + def test_metadata_helper_infers_filetype(self): + ppm = PPM().Read(self.data, ReadFrames=False) + metadata = get_metadata(ppm) + self.assertEqual(metadata["Current filename"], "74CC1F_0D3AA40F2B3A0_000.ppm") + self.assertEqual(metadata["Number of frames"], 3) + self.assertIn("Frame speed", metadata) + + def test_image_export(self): + ppm = PPM().Read(self.data, DecodeThumbnail=True, ReadFrames=False) + with tempfile.TemporaryDirectory() as tmp: + output = Path(tmp) / "thumb.png" + self.assertTrue(WriteImage(ppm.GetThumbnail(), str(output))) + self.assertGreater(output.stat().st_size, 0) + + +class NTFTTests(unittest.TestCase): + def test_exact_roundtrip_news(self): + raw = NEWS_NTFT.read_bytes() + image = NTFT().Read(raw, (32, 32)) + self.assertTrue(image) + self.assertEqual(image.Pack(), raw) + + def test_exact_roundtrip_kaeru(self): + raw = KAERU_NTFT.read_bytes() + image = NTFT().Read(raw, (36, 30)) + self.assertTrue(image) + self.assertEqual(image.Pack(), raw) + + +class UGOTests(unittest.TestCase): + def _roundtrip_xml(self, path: Path): + ugo = UGO().ReadXML(str(path), False) + self.assertTrue(ugo) + packed = ugo.Pack() + self.assertIsInstance(packed, bytes) + self.assertEqual(packed[:4], b"UGAR") + decoded = UGO().Read(packed) + self.assertTrue(decoded) + # Embedded-file names are XML-side metadata and are not stored in the + # binary UGO format. The meaningful binary round-trip is idempotence. + self.assertEqual(decoded.Pack(), packed) + + def test_index_xml(self): + self._roundtrip_xml(INDEX_UGOXML) + + def test_inbox_xml(self): + self._roundtrip_xml(INBOX_UGOXML) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_server_resources.py b/tests/test_server_resources.py new file mode 100644 index 0000000..2e79d99 --- /dev/null +++ b/tests/test_server_resources.py @@ -0,0 +1,124 @@ +from __future__ import annotations + +import importlib +import sys +import types +import unittest +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] + + +def install_twisted_stub(): + """Install only the Twisted surface needed to smoke-test this project.""" + if importlib.util.find_spec("twisted") is not None: + return + + twisted = types.ModuleType("twisted") + web = types.ModuleType("twisted.web") + resource_mod = types.ModuleType("twisted.web.resource") + static_mod = types.ModuleType("twisted.web.static") + internet_mod = types.ModuleType("twisted.internet") + + class Resource: + isLeaf = False + + def __init__(self): + self.children = {} + + def putChild(self, name, child): + if not isinstance(name, bytes): + raise TypeError("Twisted child names must be bytes") + self.children[name] = child + + def getChild(self, name, request): + return self + + def getChildWithDefault(self, name, request): + return self.children.get(name, self.getChild(name, request)) + + class File(Resource): + def __init__(self, path): + super().__init__() + self.path = path + + def render(self, request): + p = Path(self.path) + return p.read_bytes() if p.is_file() else b"" + + class Reactor: + def __init__(self): + self.calls = [] + + def callLater(self, delay, func, *args, **kwargs): + self.calls.append((delay, func, args, kwargs)) + return object() + + def callInThread(self, func, *args, **kwargs): + return func(*args, **kwargs) + + resource_mod.Resource = Resource + static_mod.File = File + web.resource = resource_mod + web.static = static_mod + internet_mod.reactor = Reactor() + twisted.web = web + twisted.internet = internet_mod + + sys.modules.update( + { + "twisted": twisted, + "twisted.web": web, + "twisted.web.resource": resource_mod, + "twisted.web.static": static_mod, + "twisted.internet": internet_mod, + } + ) + + +class ResourceTreeTests(unittest.TestCase): + @classmethod + def setUpClass(cls): + install_twisted_stub() + cls.old_cwd = Path.cwd() + import os + os.chdir(ROOT) + import hatena + cls.hatena = hatena + cls.root = hatena.Setup() + + @classmethod + def tearDownClass(cls): + import os + os.chdir(cls.old_cwd) + + def test_core_resource_tree_loads(self): + region = self.root.dsResource.region + expected = { + b"index.ugo", + b"inbox.ugo", + b"movie", + b"post", + b"frontpage", + b"help", + b"eula_list.tsv", + } + self.assertTrue(expected.issubset(region.children)) + self.assertIn(b"flipnote.post", region.children[b"post"].children) + self.assertIn(b"hotmovies.ugo", region.children[b"frontpage"].children) + self.assertIn(b"likedmovies.ugo", region.children[b"frontpage"].children) + self.assertIn(b"newmovies.ugo", region.children[b"frontpage"].children) + + def test_prepacked_ugo_resources_are_binary(self): + region = self.root.dsResource.region + self.assertTrue(region.children[b"index.ugo"].ugofile.startswith(b"UGAR")) + self.assertTrue(region.children[b"inbox.ugo"].ugofile.startswith(b"UGAR")) + + def test_hot_page_builds_from_database(self): + hot = self.root.dsResource.region.children[b"frontpage"].children[b"hotmovies.ugo"] + self.assertGreaterEqual(len(hot.pages), 1) + self.assertTrue(hot.pages[0].startswith(b"UGAR")) + + +if __name__ == "__main__": + unittest.main()