commit
ce2b19ebd0
|
@ -0,0 +1,7 @@
|
|||
# GoLand
|
||||
.idea/
|
||||
|
||||
|
||||
# Binaries
|
||||
/falseknees
|
||||
/falseknees.exe
|
|
@ -0,0 +1,19 @@
|
|||
Copyright (c) 2021 Etzelia
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -0,0 +1,17 @@
|
|||
GO ?= go
|
||||
|
||||
.PHONY: build
|
||||
build:
|
||||
$(GO) build ./cmd/falseknees
|
||||
|
||||
.PHONY: vet
|
||||
vet:
|
||||
$(GO) vet ./...
|
||||
|
||||
.PHONY: fmt
|
||||
fmt:
|
||||
$(GO) fmt ./...
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
$(GO) test -race ./...
|
|
@ -0,0 +1,27 @@
|
|||
# FalseKnees
|
||||
|
||||
This is definitely not real API for [FalseKnees](https://www.falseknees.com).
|
||||
|
||||
By that I mean to say FK does not *have* an API, so this is a glorified HTML parser.
|
||||
|
||||
Please be considerate of the fact that this is not a real API and so it is pulling entire HTML pages
|
||||
to parse.
|
||||
|
||||
|
||||
## Current Comic
|
||||
|
||||
[FalseKnees](https://www.falseknees.com) `/index.html` page contains a redirect to get the latest
|
||||
comic number. This library leverages that page to get the current comic, **however** in an effort
|
||||
to reduce HTTP calls against full HTML pages, the library has a built-in interval of 30 minutes.
|
||||
|
||||
This means that if you get the current comic at 12:00 and FK adds a new comic at 12:05, you
|
||||
won't get the new current comic until 12:30.
|
||||
|
||||
Currently the following funcs retrieve the current comic number:
|
||||
|
||||
* `Random`
|
||||
* `Current`
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE)
|
|
@ -0,0 +1,29 @@
|
|||
package falseknees
|
||||
|
||||
import "net/http"
|
||||
|
||||
// Client is a FalseKnees client
|
||||
type Client struct {
|
||||
http *http.Client
|
||||
}
|
||||
|
||||
// New returns a new Client
|
||||
func New(opts ...ClientOption) *Client {
|
||||
c := &Client{
|
||||
http: http.DefaultClient,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(c)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// ClientOption is options for a Client
|
||||
type ClientOption func(*Client)
|
||||
|
||||
// WithHTTP is a ClientOption for using a different http.Client
|
||||
func WithHTTP(client *http.Client) ClientOption {
|
||||
return func(c *Client) {
|
||||
c.http = client
|
||||
}
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"git.birbmc.com/Etzelia/falseknees"
|
||||
)
|
||||
|
||||
var (
|
||||
randomFlag bool
|
||||
imageFlag bool
|
||||
outFlag string
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.BoolVar(&randomFlag, "random", false, "get a random comic")
|
||||
flag.BoolVar(&imageFlag, "image", false, "get the image response for a comic")
|
||||
flag.StringVar(&outFlag, "out", "", "where to write the response (default: stdout)")
|
||||
flag.Parse()
|
||||
|
||||
comicNum := 0
|
||||
if flag.NArg() > 0 {
|
||||
arg := flag.Arg(0)
|
||||
i, err := strconv.Atoi(arg)
|
||||
if err != nil {
|
||||
fmt.Printf("Specific comic must be a number: %v\n", err)
|
||||
return
|
||||
}
|
||||
comicNum = i
|
||||
}
|
||||
out := os.Stdout
|
||||
if outFlag != "" {
|
||||
fi, err := os.Create(outFlag)
|
||||
if err != nil {
|
||||
fmt.Printf("Could not create file %s: %v\n", outFlag, err)
|
||||
return
|
||||
}
|
||||
defer fi.Close()
|
||||
out = fi
|
||||
}
|
||||
|
||||
if err := run(comicNum, out); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
func run(comicNum int, out io.WriteCloser) error {
|
||||
|
||||
client := falseknees.New()
|
||||
var comic *falseknees.Comic
|
||||
var err error
|
||||
if randomFlag {
|
||||
comic, err = client.Random(context.Background())
|
||||
} else if comicNum == 0 {
|
||||
comic, err = client.Current(context.Background())
|
||||
} else {
|
||||
comic, err = client.Comic(context.Background(), comicNum)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if imageFlag {
|
||||
return image(comic.Img, out)
|
||||
}
|
||||
|
||||
format := `Comic: %d
|
||||
Title: %s
|
||||
Image: %s
|
||||
`
|
||||
if _, err := fmt.Fprintf(out, format,
|
||||
comic.Num,
|
||||
comic.Title,
|
||||
comic.Img); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func image(img string, out io.WriteCloser) error {
|
||||
req, err := http.NewRequest(http.MethodGet, img, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if _, err := io.Copy(out, resp.Body); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
package falseknees
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
updateInterval = time.Minute * 30
|
||||
baseURL = "https://www.falseknees.com/"
|
||||
currentRe = regexp.MustCompile(`window\.location\.href.+"(.+)\.html"`)
|
||||
imageRe = regexp.MustCompile(`src="(imgs.+\.png)".+title="(.+)"`)
|
||||
|
||||
current int
|
||||
lastUpdate time.Time
|
||||
)
|
||||
|
||||
// Comic is a FalseKnees comic
|
||||
type Comic struct {
|
||||
Num int
|
||||
Title string
|
||||
Img string
|
||||
}
|
||||
|
||||
// Comic returns a specific Comic
|
||||
func (c *Client) Comic(ctx context.Context, num int) (*Comic, error) {
|
||||
return c.comic(ctx, num)
|
||||
}
|
||||
|
||||
// Current returns the current Comic
|
||||
func (c *Client) Current(ctx context.Context) (*Comic, error) {
|
||||
if err := c.updateCurrent(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.Comic(ctx, current)
|
||||
}
|
||||
|
||||
// Random returns a random Comic
|
||||
func (c *Client) Random(ctx context.Context) (*Comic, error) {
|
||||
if err := c.updateCurrent(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
return c.Comic(ctx, rand.Intn(current)+1)
|
||||
}
|
||||
|
||||
func (c *Client) updateCurrent(ctx context.Context) error {
|
||||
now := time.Now()
|
||||
if !lastUpdate.IsZero() && lastUpdate.After(now.Add(-updateInterval)) {
|
||||
return nil
|
||||
}
|
||||
lastUpdate = now
|
||||
|
||||
u := fmt.Sprintf("%sindex.html", baseURL)
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resp, err := c.http.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("could not get page for index: %s", resp.Status)
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
match := currentRe.FindStringSubmatch(string(body))
|
||||
if len(match) == 0 {
|
||||
return errors.New("could not find current comic")
|
||||
}
|
||||
|
||||
curr, err := strconv.Atoi(match[1])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
current = curr
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) comic(ctx context.Context, num int) (*Comic, error) {
|
||||
u := fmt.Sprintf("%s%d.html", baseURL, num)
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := c.http.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("could not get page for comic %d: %s", num, resp.Status)
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
match := imageRe.FindStringSubmatch(string(body))
|
||||
if len(match) == 0 {
|
||||
return nil, fmt.Errorf("could not find comic #%d", num)
|
||||
}
|
||||
|
||||
return &Comic{
|
||||
Num: num,
|
||||
Title: match[2],
|
||||
Img: fmt.Sprintf("%s%s", baseURL, match[1]),
|
||||
}, nil
|
||||
}
|
|
@ -0,0 +1,483 @@
|
|||
package falseknees
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
server *httptest.Server
|
||||
client *Client
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
handler := func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path == "/index.html" {
|
||||
_, _ = w.Write(indexHTML)
|
||||
return
|
||||
}
|
||||
if r.URL.Path == "/389.html" {
|
||||
_, _ = w.Write(currentHTML)
|
||||
return
|
||||
}
|
||||
if r.URL.Path == "/252.html" {
|
||||
_, _ = w.Write(bunnyHTML)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
}
|
||||
|
||||
server = httptest.NewServer(http.HandlerFunc(handler))
|
||||
baseURL = server.URL + "/"
|
||||
currentComic.Img = fmt.Sprintf("%simgs/389.png", baseURL)
|
||||
bunnyComic.Img = fmt.Sprintf("%simgs/252.png", baseURL)
|
||||
client = New()
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestCurrent(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
comic, err := client.Current(context.Background())
|
||||
if err != nil {
|
||||
t.Logf("could not get current comic: %v\n", err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
if *comic != currentComic {
|
||||
t.Log("comic does not match test data")
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
||||
func TestComic(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
comic, err := client.Comic(context.Background(), 252)
|
||||
if err != nil {
|
||||
t.Logf("could not get comic 252: %v\n", err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
if *comic != bunnyComic {
|
||||
t.Log("comic does not match test data")
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
currentComic = Comic{
|
||||
Num: 389,
|
||||
Title: "that's the good stuff",
|
||||
}
|
||||
bunnyComic = Comic{
|
||||
Num: 252,
|
||||
Title: "Spring is the fucking greatest shit",
|
||||
}
|
||||
|
||||
indexHTML = []byte(`<!DOCTYPE html
|
||||
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<head>
|
||||
<meta name="description"
|
||||
content="False Knees is a webcomic written by Joshua Barkman. All silly nonsense is my own." />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
|
||||
<meta http-equiv="refresh" content="0; URL=389.html" />
|
||||
<script type="text/javascript">
|
||||
window.location.href = "389.html"
|
||||
</script>
|
||||
|
||||
<!-- Favicon -->
|
||||
<link rel="icon" type="image/png" href="imgs/favicon.png" sizes="96x96">
|
||||
<!-- Facebook Meta tags -->
|
||||
<meta property="og:title" content="False Knees" />
|
||||
<meta property="og:type" content="blog" />
|
||||
<meta property="og:url" content="http://www.falseknees.com/index.html" />
|
||||
<meta property="og:image" content="http://www.falseknees.com/imgs/389.png" />
|
||||
<meta property="og:site_name" content="False Knees" />
|
||||
<meta property="fb:admins" content="1646220005" />
|
||||
|
||||
<link rel="image_src" href="imgs/389.png" />
|
||||
<link type="text/css" rel="stylesheet" href="stylesheet.css" />
|
||||
<title>Page Redirection</title>
|
||||
|
||||
<!-- Google Analytics -->
|
||||
<script type="text/javascript">
|
||||
var _gaq = _gaq || [];
|
||||
var pluginUrl =
|
||||
'//www.google-analytics.com/plugins/ga/inpage_linkid.js';
|
||||
_gaq.push(['_require', 'inpage_linkid', pluginUrl]);
|
||||
_gaq.push(['_setAccount', 'UA-37345913-1']);
|
||||
_gaq.push(['_setDomainName', 'falseknees.com']);
|
||||
_gaq.push(['_trackPageview']);
|
||||
|
||||
(function() {
|
||||
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
||||
})();
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="fb-root"></div>
|
||||
<script>
|
||||
(function(d, s, id) {
|
||||
var js, fjs = d.getElementsByTagName(s)[0];
|
||||
if (d.getElementById(id)) return;
|
||||
js = d.createElement(s); js.id = id;
|
||||
js.src = "//connect.facebook.net/en_GB/sdk.js#xfbml=1&version=v2.0";
|
||||
fjs.parentNode.insertBefore(js, fjs);
|
||||
}(document, 'script', 'facebook-jssdk'));
|
||||
</script>
|
||||
|
||||
<!-- Title Image -->
|
||||
<table align="center">
|
||||
<tr>
|
||||
<td>
|
||||
<div id="title">
|
||||
<a href="index.html"><img src="imgs/falseknees.png" width="800" /></a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- New Button Placement -->
|
||||
<div align="center">
|
||||
<p>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href="about.html"
|
||||
title=""><img src="imgs/aboutoff.png" height="50" alt="About" onmouseover="this.src='imgs/abouton.png'" onmouseout="this.src='imgs/aboutoff.png'" /></a>
|
||||
</td>
|
||||
<td><a title=""><img src="imgs/stara.png" height="50" alt="" /></a></td>
|
||||
<td><a href="https://false-knees.myshopify.com/"
|
||||
title=""><img src="imgs/store.png" height="50" alt="Store" onmouseover="this.src='imgs/storeon.png'" onmouseout="this.src='imgs/store.png'" /></a>
|
||||
</td>
|
||||
<td><a title=""><img src="imgs/starb.png" height="50" alt="" /></a></td>
|
||||
<td><a href="https://www.patreon.com/falseknees?ty=h"><img src="imgs/patron.png" height="50" onmouseover="this.src='imgs/patroff.png'" onmouseout="this.src='imgs/patron.png'"/></a>
|
||||
</td>
|
||||
<td><a title=""><img src="imgs/starc.png" height="50" alt="" /></a></td>
|
||||
<td><a href="book.html"
|
||||
title=""><img src="imgs/book.png" height="40" alt="About" onmouseover="this.src='imgs/bookon.png'" onmouseout="this.src='imgs/book.png'" /></a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Comic -->
|
||||
<div>
|
||||
<img src="imgs/389.png" width="600" title="that's the good stuff" />
|
||||
</div>
|
||||
|
||||
<!-- Descriptive Text Box -->
|
||||
<!-- Descriptive Text Box -->
|
||||
<div align="center">
|
||||
</div>
|
||||
|
||||
<!-- Navigation Buttons -->
|
||||
<div align="center">
|
||||
<p>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href="1.html"
|
||||
title=""><img src="imgs/first.png" height="60" alt="First" onmouseover="this.src='imgs/firston.png'" onmouseout="this.src='imgs/first.png'" /></a>
|
||||
</td>
|
||||
<td><a href="388.html"
|
||||
title=""><img src="imgs/previous.png" height="60" alt="Previous" onmouseover="this.src='imgs/previouson.png'" onmouseout="this.src='imgs/previous.png'" /></a>
|
||||
</td>
|
||||
<td><a href="archive.html"
|
||||
title=""><img src="imgs/archive.png" height="60" alt="Archive" onmouseover="this.src='imgs/archive2.png'" onmouseout="this.src='imgs/archive.png'" /></a>
|
||||
</td>
|
||||
<td><a href="index.html"
|
||||
title=""><img src="imgs/next.png" height="60" alt="Next" onmouseover="this.src='imgs/nexton.png'" onmouseout="this.src='imgs/next.png'" /></a>
|
||||
</td>
|
||||
<td><a href="index.html"
|
||||
title=""><img src="imgs/last.png" height="60" alt="Last" onmouseover="this.src='imgs/laston.png'" onmouseout="this.src='imgs/last.png'" /></a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Social Media -->
|
||||
<table class="social" align="center">
|
||||
<tr>
|
||||
<td><a href="http://falseknees.tumblr.com/"><img src="imgs/TumblrButton.png" width="60" onmouseover="this.src='imgs/TumblrButtonOn.png'" onmouseout="this.src='imgs/TumblrButton.png'"/></a>
|
||||
</td>
|
||||
<td><a href="https://instagram.com/FalseKnees"><img src="imgs/instagram.png" width="60" onmouseover="this.src='imgs/instagramon.png'" onmouseout="this.src='imgs/instagram.png'"/></a>
|
||||
</td>
|
||||
<td><a href="https://www.facebook.com/FalseKnees?ref=hl"><img src="imgs/FacebookButton.png" width="60" onmouseover="this.src='imgs/FacebookButtonOn.png'" onmouseout="this.src='imgs/FacebookButton.png'"/></a>
|
||||
</td>
|
||||
<td><a href="http://www.webtoons.com/en/challenge/false-knees/list?title_no=79544"><img src="imgs/webtooff.png" width="60" onmouseover="this.src='imgs/webtoon.png'" onmouseout="this.src='imgs/webtooff.png'"/></a>
|
||||
</td>
|
||||
<td><a href="https://tapas.io/series/FalseKnees"><img src="imgs/tap.png" width="60" onmouseover="this.src='imgs/tapon.png'" onmouseout="this.src='imgs/tap.png'"/></a>
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- Copyright -->
|
||||
<div>
|
||||
<p>False Knees © 2013-whenever Joshua Barkman</p>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>`)
|
||||
|
||||
currentHTML = []byte(`<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta name="description" content="False Knees is a webcomic written by Joshua Barkman. All silly nonsense is my own." />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<!-- Favicon -->
|
||||
<link rel="icon" type="image/png" href="imgs/favicon.png" sizes="96x96">
|
||||
<!-- Facebook Meta tags -->
|
||||
<meta property="og:title" content="False Knees" />
|
||||
<meta property="og:type" content="blog" />
|
||||
<meta property="og:url" content="http://www.falseknees.com/389.html" />
|
||||
<meta property="og:image" content="http://www.falseknees.com/imgs/389.png" />
|
||||
<meta property="og:site_name" content="False Knees" />
|
||||
<meta property="fb:admins" content="1646220005" />
|
||||
|
||||
<link rel="image_src" href="imgs/389.png" />
|
||||
<link type="text/css" rel="stylesheet" href="stylesheet.css" />
|
||||
<title>False Knees</title>
|
||||
|
||||
<!-- Google Analytics -->
|
||||
<script type="text/javascript">
|
||||
|
||||
var _gaq = _gaq || [];
|
||||
var pluginUrl =
|
||||
'//www.google-analytics.com/plugins/ga/inpage_linkid.js';
|
||||
_gaq.push(['_require', 'inpage_linkid', pluginUrl]);
|
||||
_gaq.push(['_setAccount', 'UA-37345913-1']);
|
||||
_gaq.push(['_setDomainName', 'falseknees.com']);
|
||||
_gaq.push(['_trackPageview']);
|
||||
|
||||
(function() {
|
||||
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
||||
})();
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="fb-root"></div>
|
||||
<script>(function(d, s, id) {
|
||||
var js, fjs = d.getElementsByTagName(s)[0];
|
||||
if (d.getElementById(id)) return;
|
||||
js = d.createElement(s); js.id = id;
|
||||
js.src = "//connect.facebook.net/en_GB/sdk.js#xfbml=1&version=v2.0";
|
||||
fjs.parentNode.insertBefore(js, fjs);
|
||||
}(document, 'script', 'facebook-jssdk'));</script>
|
||||
|
||||
<!-- Title Image -->
|
||||
<table align="center">
|
||||
<tr>
|
||||
<td><div id="title">
|
||||
<a href="index.html"><img src="imgs/falseknees.png" width="800" /></a>
|
||||
</div></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- New Button Placement -->
|
||||
<div align="center">
|
||||
<p>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href="about.html" title=""><img src="imgs/aboutoff.png" height="50" alt="About" onmouseover="this.src='imgs/abouton.png'" onmouseout="this.src='imgs/aboutoff.png'" /></a></td>
|
||||
<td><a title=""><img src="imgs/stara.png" height="50" alt="" /></a></td>
|
||||
<td><a href="https://false-knees.myshopify.com/" title=""><img src="imgs/store.png" height="50" alt="Store" onmouseover="this.src='imgs/storeon.png'" onmouseout="this.src='imgs/store.png'" /></a></td>
|
||||
<td><a title=""><img src="imgs/starb.png" height="50" alt="" /></a></td>
|
||||
<td><a href="https://www.patreon.com/falseknees?ty=h"><img src="imgs/patron.png" height="50" onmouseover="this.src='imgs/patroff.png'" onmouseout="this.src='imgs/patron.png'"/></a></td>
|
||||
<td><a title=""><img src="imgs/starc.png" height="50" alt="" /></a></td>
|
||||
<td><a href="book.html" title=""><img src="imgs/book.png" height="40" alt="About" onmouseover="this.src='imgs/bookon.png'" onmouseout="this.src='imgs/book.png'" /></a></td>
|
||||
</tr>
|
||||
</table></p>
|
||||
</div>
|
||||
|
||||
<!-- Comic -->
|
||||
<div>
|
||||
<img src="imgs/389.png" width="600" title="that's the good stuff" />
|
||||
</div>
|
||||
|
||||
<!-- Descriptive Text Box -->
|
||||
<!-- Descriptive Text Box -->
|
||||
<div align="center">
|
||||
</div>
|
||||
|
||||
<!-- Navigation Buttons -->
|
||||
<div align="center">
|
||||
<p>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href="1.html" title=""><img src="imgs/first.png" height="60" alt="First" onmouseover="this.src='imgs/firston.png'" onmouseout="this.src='imgs/first.png'" /></a></td>
|
||||
<td><a href="388.html" title=""><img src="imgs/previous.png" height="60" alt="Previous" onmouseover="this.src='imgs/previouson.png'" onmouseout="this.src='imgs/previous.png'" /></a></td>
|
||||
<td><a href="archive.html" title=""><img src="imgs/archive.png" height="60" alt="Archive" onmouseover="this.src='imgs/archive2.png'" onmouseout="this.src='imgs/archive.png'" /></a></td>
|
||||
<td><a href="389.html" title=""><img src="imgs/next.png" height="60" alt="Next" onmouseover="this.src='imgs/nexton.png'" onmouseout="this.src='imgs/next.png'" /></a></td>
|
||||
<td><a href="index.html" title=""><img src="imgs/last.png" height="60" alt="Last" onmouseover="this.src='imgs/laston.png'" onmouseout="this.src='imgs/last.png'" /></a></td>
|
||||
</tr>
|
||||
</table></p>
|
||||
</div>
|
||||
|
||||
<!-- Social Media -->
|
||||
<table class="social" align="center">
|
||||
<tr>
|
||||
<td><a href="http://falseknees.tumblr.com/"><img src="imgs/TumblrButton.png" width="60" onmouseover="this.src='imgs/TumblrButtonOn.png'" onmouseout="this.src='imgs/TumblrButton.png'"/></a>
|
||||
</td>
|
||||
<td><a href="https://instagram.com/FalseKnees"><img src="imgs/instagram.png" width="60" onmouseover="this.src='imgs/instagramon.png'" onmouseout="this.src='imgs/instagram.png'"/></a>
|
||||
</td>
|
||||
<td><a href="https://www.facebook.com/FalseKnees?ref=hl"><img src="imgs/FacebookButton.png" width="60" onmouseover="this.src='imgs/FacebookButtonOn.png'" onmouseout="this.src='imgs/FacebookButton.png'"/></a>
|
||||
</td>
|
||||
<td><a href="http://www.webtoons.com/en/challenge/false-knees/list?title_no=79544"><img src="imgs/webtooff.png" width="60" onmouseover="this.src='imgs/webtoon.png'" onmouseout="this.src='imgs/webtooff.png'"/></a>
|
||||
</td>
|
||||
<td><a href="https://tapas.io/series/FalseKnees"><img src="imgs/tap.png" width="60" onmouseover="this.src='imgs/tapon.png'" onmouseout="this.src='imgs/tap.png'"/></a>
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- Copyright -->
|
||||
<div>
|
||||
<p>False Knees © 2013-whenever Joshua Barkman</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
`)
|
||||
|
||||
bunnyHTML = []byte(`<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta name="description" content="False Knees is a webcomic written by Joshua Barkman. All silly nonsense is my own." />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<!-- Favicon -->
|
||||
<link rel="icon" type="image/png" href="imgs/favicon.png" sizes="96x96">
|
||||
<!-- Facebook Meta tags -->
|
||||
<meta property="og:title" content="False Knees" />
|
||||
<meta property="og:type" content="blog" />
|
||||
<meta property="og:url" content="http://www.falseknees.com/252.html" />
|
||||
<meta property="og:image" content="http://www.falseknees.com/imgs/252.png" />
|
||||
<meta property="og:site_name" content="False Knees" />
|
||||
<meta property="fb:admins" content="1646220005" />
|
||||
|
||||
<link rel="image_src" href="imgs/252.png" />
|
||||
<link type="text/css" rel="stylesheet" href="stylesheet.css" />
|
||||
<title>False Knees</title>
|
||||
|
||||
<!-- Google Analytics -->
|
||||
<script type="text/javascript">
|
||||
|
||||
var _gaq = _gaq || [];
|
||||
var pluginUrl =
|
||||
'//www.google-analytics.com/plugins/ga/inpage_linkid.js';
|
||||
_gaq.push(['_require', 'inpage_linkid', pluginUrl]);
|
||||
_gaq.push(['_setAccount', 'UA-37345913-1']);
|
||||
_gaq.push(['_setDomainName', 'falseknees.com']);
|
||||
_gaq.push(['_trackPageview']);
|
||||
|
||||
(function() {
|
||||
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
||||
})();
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="fb-root"></div>
|
||||
<script>(function(d, s, id) {
|
||||
var js, fjs = d.getElementsByTagName(s)[0];
|
||||
if (d.getElementById(id)) return;
|
||||
js = d.createElement(s); js.id = id;
|
||||
js.src = "//connect.facebook.net/en_GB/sdk.js#xfbml=1&version=v2.0";
|
||||
fjs.parentNode.insertBefore(js, fjs);
|
||||
}(document, 'script', 'facebook-jssdk'));</script>
|
||||
|
||||
<!-- Title Image -->
|
||||
<table align="center">
|
||||
<tr>
|
||||
<td><div id="title">
|
||||
<a href="index.html"><img src="imgs/falseknees.png" width="800" /></a>
|
||||
</div></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- New Button Placement -->
|
||||
<div align="center">
|
||||
<p>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href="about.html" title=""><img src="imgs/aboutoff.png" height="50" alt="About" onmouseover="this.src='imgs/abouton.png'" onmouseout="this.src='imgs/aboutoff.png'" /></a></td>
|
||||
<td><a title=""><img src="imgs/stara.png" height="50" alt="" /></a></td>
|
||||
<td><a href="https://false-knees.myshopify.com/collections/comic-prints" title=""><img src="imgs/store.png" height="50" alt="Store" onmouseover="this.src='imgs/storeon.png'" onmouseout="this.src='imgs/store.png'" /></a></td>
|
||||
<td><a title=""><img src="imgs/starb.png" height="50" alt="" /></a></td>
|
||||
<td><a href="https://www.patreon.com/falseknees?ty=h"><img src="imgs/patron.png" height="50" onmouseover="this.src='imgs/patroff.png'" onmouseout="this.src='imgs/patron.png'"/></a></td>
|
||||
<td><a title=""><img src="imgs/starc.png" height="50" alt="" /></a></td>
|
||||
<td><a href="book.html" title=""><img src="imgs/book.png" height="40" alt="About" onmouseover="this.src='imgs/bookon.png'" onmouseout="this.src='imgs/book.png'" /></a></td>
|
||||
</tr>
|
||||
</table></p>
|
||||
</div>
|
||||
|
||||
<!-- Comic -->
|
||||
<div>
|
||||
<img src="imgs/252.png" width="600" title="Spring is the fucking greatest shit" />
|
||||
</div>
|
||||
|
||||
<!-- Descriptive Text Box -->
|
||||
<!-- Descriptive Text Box -->
|
||||
<div align="center">
|
||||
</div>
|
||||
|
||||
<!-- Navigation Buttons -->
|
||||
<div align="center">
|
||||
<p>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href="1.html" title=""><img src="imgs/first.png" height="60" alt="First" onmouseover="this.src='imgs/firston.png'" onmouseout="this.src='imgs/first.png'" /></a></td>
|
||||
<td><a href="251.html" title=""><img src="imgs/previous.png" height="60" alt="Previous" onmouseover="this.src='imgs/previouson.png'" onmouseout="this.src='imgs/previous.png'" /></a></td>
|
||||
<td><a href="archive.html" title=""><img src="imgs/archive.png" height="60" alt="Archive" onmouseover="this.src='imgs/archive2.png'" onmouseout="this.src='imgs/archive.png'" /></a></td>
|
||||
<td><a href="253.html" title=""><img src="imgs/next.png" height="60" alt="Next" onmouseover="this.src='imgs/nexton.png'" onmouseout="this.src='imgs/next.png'" /></a></td>
|
||||
<td><a href="index.html" title=""><img src="imgs/last.png" height="60" alt="Last" onmouseover="this.src='imgs/laston.png'" onmouseout="this.src='imgs/last.png'" /></a></td>
|
||||
</tr>
|
||||
</table></p>
|
||||
</div>
|
||||
|
||||
<!-- Social Media -->
|
||||
<table class="social" align="center">
|
||||
<tr>
|
||||
<td><a href="http://falseknees.tumblr.com/"><img src="imgs/TumblrButton.png" width="60" onmouseover="this.src='imgs/TumblrButtonOn.png'" onmouseout="this.src='imgs/TumblrButton.png'"/></a>
|
||||
</td>
|
||||
<td><a href="https://instagram.com/FalseKnees"><img src="imgs/instagram.png" width="60" onmouseover="this.src='imgs/instagramon.png'" onmouseout="this.src='imgs/instagram.png'"/></a>
|
||||
</td>
|
||||
<td><a href="https://www.facebook.com/FalseKnees?ref=hl"><img src="imgs/FacebookButton.png" width="60" onmouseover="this.src='imgs/FacebookButtonOn.png'" onmouseout="this.src='imgs/FacebookButton.png'"/></a>
|
||||
</td>
|
||||
<td><a href="http://www.webtoons.com/en/challenge/false-knees/list?title_no=79544"><img src="imgs/webtooff.png" width="60" onmouseover="this.src='imgs/webtoon.png'" onmouseout="this.src='imgs/webtooff.png'"/></a>
|
||||
</td>
|
||||
<td><a href="https://tapas.io/series/FalseKnees"><img src="imgs/tap.png" width="60" onmouseover="this.src='imgs/tapon.png'" onmouseout="this.src='imgs/tap.png'"/></a>
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- Copyright -->
|
||||
<div>
|
||||
<p>False Knees © 2013-whenever Joshua Barkman</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
`)
|
||||
)
|
Reference in New Issue