1# -*- coding: utf-8 -*-
2# Copyright (C) 2004-2008 Tristan Seligmann and Jonathan Jacobs
3# Copyright (C) 2012-2014 Bastian Kleineidam
4# Copyright (C) 2015-2020 Tobias Gruetzmacher
5# Copyright (C) 2019-2020 Daniel Ring
6
7from __future__ import absolute_import, division, print_function
8from re import compile, escape
9
10from ..util import tagre
11from ..scraper import _BasicScraper, _ParserScraper
12from ..helpers import indirectStarter, joinPathPartsNamer, xpath_class
13from .common import _ComicControlScraper, _WPNaviIn, _WordPressScraper
14
15
16class FalconTwin(_BasicScraper):
17    url = 'http://www.falcontwin.com/'
18    stripUrl = url + 'index.html?strip=%s'
19    firstStripUrl = stripUrl % '0'
20    imageSearch = compile(r'"(strips/.+?)"')
21    prevSearch = compile(r'"prev"><a href="(index.+?)"')
22    help = 'Index format: nnn'
23
24
25class Faneurysm(_WPNaviIn):
26    url = 'http://hijinksensue.com/comic/think-only-tree/'
27    firstStripUrl = 'http://hijinksensue.com/comic/captains-prerogative/'
28    endOfLife = True
29
30
31class FantasyRealms(_ParserScraper):
32    stripUrl = ('https://web.archive.org/web/20161204192651/'
33        'http://fantasyrealmsonline.com/manga/%s.php')
34    url = stripUrl % '091'
35    firstStripUrl = stripUrl % '001'
36    imageSearch = '//img[contains(@src, "/manga/0")]'
37    prevSearch = '//a[img[contains(@src, "nav-back")]]'
38    endOfLife = True
39    help = 'Index format: nnn'
40
41
42class FarToTheNorth(_ComicControlScraper):
43    url = 'http://www.farnorthcomic.com/'
44    stripUrl = url + 'comic/%s'
45    firstStripUrl = stripUrl % 'don39t-tell'
46
47
48class FauxPas(_ParserScraper):
49    url = 'http://www.ozfoxes.net/cgi/pl-fp1.cgi'
50    stripUrl = url + '?%s'
51    firstStripUrl = stripUrl % '1'
52    imageSearch = '//img[@name]'
53    prevSearch = '//a[img[@alt="Previous"]]'
54    help = 'Index format: nnn'
55
56
57class FireflyCross(_WordPressScraper):
58    url = 'http://www.fireflycross.pensandtales.com/'
59    firstStripUrl = url + '?comic=05062002'
60
61
62class FirstWorldProblems(_ParserScraper):
63    url = ('https://web.archive.org/web/20150710053456/'
64        'http://bradcolbow.com/archive/C5/')
65    stripUrl = url + '%s/'
66    firstStripUrl = stripUrl % 'P10'
67    imageSearch = '//div[{}]//img'.format(xpath_class('entry'))
68    prevSearch = '//a[{}]'.format(xpath_class('prev'))
69    multipleImagesPerStrip = True
70    endOfLife = True
71
72
73class FlakyPastry(_BasicScraper):
74    baseUrl = 'http://flakypastry.runningwithpencils.com/'
75    url = baseUrl + 'index.php'
76    stripUrl = baseUrl + 'comic.php?strip_id=%s'
77    firstStripUrl = stripUrl % '0'
78    imageSearch = compile(r'<img src="(comics/.+?)"')
79    prevSearch = compile(r'<a href="(.+?)".+?btn_back')
80    help = 'Index format: nnnn'
81
82
83class Flemcomics(_ParserScraper):
84    url = ('https://web.archive.org/web/20180414110349/'
85        'http://www.flemcomics.com/')
86    stripUrl = url + 'd/%s.html'
87    firstStripUrl = stripUrl % '19980101'
88    imageSearch = '//img[{}]'.format(xpath_class('ksc'))
89    prevSearch = '//a[@rel="prev"]'
90    endOfLife = True
91    help = 'Index format: yyyymmdd'
92
93
94class Flipside(_ParserScraper):
95    url = 'http://flipside.keenspot.com/comic.php'
96    stripUrl = url + '?i=%s'
97    firstStripUrl = stripUrl % '1'
98    imageSearch = '//img[contains(@src, "comic/")]'
99    prevSearch = '//a[@rel="prev"]'
100    help = 'Index format: nnnn'
101
102
103class FonFlatter(_ParserScraper):
104    url = 'https://www.fonflatter.de/'
105    stripUrl = url + '%s/'
106    firstStripUrl = url + '2005/09/20/01-begegnung-mit-batman/'
107    lang = 'de'
108    imageSearch = r'//img[re:test(@src, "/fred_\d+")]'
109    prevSearch = '//a[@rel="prev"]'
110    help = 'Index format: yyyy/mm/dd/number-stripname'
111
112    def shouldSkipUrl(self, url, data):
113        return url in (
114            self.stripUrl % "2006/11/30/adventskalender",
115            self.stripUrl % "2006/09/21/danke",
116            self.stripUrl % "2006/08/23/zgf-zuweilen-gestellte-fragen",
117            self.stripUrl % "2005/10/19/naq-never-asked-questions",
118        )
119
120
121class ForestHill(_WordPressScraper):
122    url = 'https://www.foresthillcomic.org/'
123
124
125class ForLackOfABetterComic(_BasicScraper):
126    url = 'http://forlackofabettercomic.com/'
127    rurl = r'http://(?:www\.)?forlackofabettercomic\.com/'
128    stripUrl = url + '?id=%s'
129    firstStripUrl = stripUrl % '1'
130    imageSearch = compile(tagre("img", "src", r'(%simg/comic/\d+[^"]+)' % rurl, after="comicimg"))
131    prevSearch = compile(tagre("a", "href", r'(%s\?id\=\d+)' % rurl) + r'Prev')
132    help = 'Index format: number'
133
134
135class FoxDad(_ParserScraper):
136    url = 'https://foxdad.com/'
137    stripUrl = url + 'post/%s'
138    firstStripUrl = stripUrl % '149683014997/some-people-are-just-different-support-the-comic'
139    imageSearch = '//figure[@class="photo-hires-item"]//img'
140    prevSearch = '//a[@class="previous-button"]'
141
142    def namer(self, imageUrl, pageUrl):
143        page = self.getPage(pageUrl)
144        post = page.xpath('//link[@type="application/json+oembed"]')[0].get('href')
145        post = post.replace('https://www.tumblr.com/oembed/1.0?url=https://foxdad.com/post', '')
146        post = post.replace('-support-me-on-patreon', '')
147        return post.replace('/', '-')
148
149
150class FoxTails(_ParserScraper):
151    stripUrl = 'http://foxtails.magickitsune.com/strips/%s.html'
152    url = stripUrl % 'current'
153    firstStripUrl = stripUrl % '20041024'
154    imageSearch = '//img[contains(@src, "img/2")]'
155    prevSearch = '//a[./img[contains(@src, "prev")]]'
156    endOfLife = True
157
158    def getPrevUrl(self, url, data):
159        # Include pre-reboot archive
160        if url == self.stripUrl % '20090906':
161            return self.stripUrl % '20090704'
162        return super(FoxTails, self).getPrevUrl(url, data)
163
164
165class Fragile(_ParserScraper):
166    url = ('https://web.archive.org/web/20190308203109/'
167        'http://www.fragilestory.com/')
168    imageSearch = '//div[@id="comic_strip"]/a[@class="nobg"]/img'
169    prevSearch = '//div[@id="nav_comic_a"]/a[2]'
170    firstStripUrl = url + 'strips/chapter_01'
171    endOfLife = True
172
173
174class FredoAndPidjin(_ParserScraper):
175    url = 'https://www.pidjin.net/'
176    stripUrl = url + '%s/'
177    firstStripUrl = stripUrl % '2006/02/19/goofy-monday'
178    imageSearch = '//div[%s]//img' % xpath_class("episode")
179    multipleImagesPerStrip = True
180    prevSearch = '//span[%s]/a' % xpath_class("prev")
181    latestSearch = '//section[%s]//a' % xpath_class("latest")
182    starter = indirectStarter
183    namer = joinPathPartsNamer((0, 1, 2))
184
185
186class Freefall(_ParserScraper):
187    url = 'http://freefall.purrsia.com/'
188    stripUrl = url + 'ff%d/%s%05d.htm'
189    firstStripUrl = stripUrl % (100, 'fv', 1)
190    imageSearch = '//img[contains(@src, "/ff")]'
191    prevSearch = '//a[text()="Previous"]'
192    multipleImagesPerStrip = True
193
194    def getIndexStripUrl(self, index):
195        # Get comic strip URL from index
196        index = int(index)
197        chapter = index + 100 - (index % 100)
198        color = 'fc' if index > 1252 else 'fv'
199        return self.stripUrl % (chapter, color, index)
200
201
202class FreighterTails(_ParserScraper):
203    url = 'http://www.mzzkiti.com/'
204    stripUrl = url + 'log%s.htm'
205    firstStripUrl = stripUrl % '001'
206    imageSearch = ('//img[contains(@src, "Strip")]',
207                   '//img[contains(@src, "Caption")]')
208    prevSearch = '//a[./img[contains(@src, "prev")]]'
209    endOfLife = True
210
211
212class FullFrontalNerdity(_BasicScraper):
213    url = 'http://ffn.nodwick.com/'
214    rurl = escape(url)
215    stripUrl = url + '?p=%s'
216    firstStripUrl = stripUrl % '6'
217    imageSearch = compile(tagre("img", "src", r'(%sffnstrips/\d+-\d+-\d+\.[^"]+)' % rurl))
218    prevSearch = compile(tagre("a", "href", r'(%s\?p=\d+)' % rurl, after="prev"))
219    help = 'Index format: number'
220
221
222class FunInJammies(_WordPressScraper):
223    url = ('https://web.archive.org/web/20170205105241/'
224        'http://funinjammies.com/')
225    stripUrl = url + 'comic.php?issue=%s'
226    firstStripUrl = stripUrl % '1'
227    prevSearch = '//a[text()="< Prev"]'
228    endOfLife = True
229    help = 'Index format: n (unpadded)'
230
231
232class FurPiled(_ParserScraper):
233    stripUrl = ('https://web.archive.org/web/20160404074145/'
234        'http://www.liondogworks.com/images/fp-%03d.jpg')
235    url = stripUrl % 427
236    firstStripUrl = stripUrl % 1
237    endOfLife = True
238
239    def getPrevUrl(self, url, data):
240        # Skip missing pages
241        nextStrip = int(url.rsplit('/', 1)[-1].split('.', 1)[0].replace('fp-', '')) - 1
242        if nextStrip in [407, 258, 131, 110, 97, 31]:
243            nextStrip = nextStrip - 1
244        return self.stripUrl % nextStrip
245
246    def fetchUrls(self, url, data, urlSearch):
247        # URLs are direct links to images
248        return [url]
249
250
251class FurthiaHigh(_ParserScraper):
252    url = 'http://furthiahigh.concessioncomic.com/'
253    stripUrl = url + 'index.php?pid=%s'
254    firstStripUrl = stripUrl % '20080128'
255    imageSearch = '//img[contains(@alt, "Comic")]'
256    prevSearch = '//a[./img[@alt="Previous"]]'
257    multipleImagesPerStrip = True
258