Improve source code
All checks were successful
the build was successful

This commit is contained in:
Peter Stuifzand 2019-03-07 20:55:25 +01:00
parent 3fe9d65cdf
commit 70f5fb82f9
Signed by: peter
GPG Key ID: 374322D56E5209E8
10 changed files with 159 additions and 87 deletions

18
.pre-commit-config.yaml Normal file
View File

@ -0,0 +1,18 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.1.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-merge-conflict
- id: check-added-large-files
- repo: https://github.com/dnephin/pre-commit-golang
rev: master
hooks:
- id: go-vet
- id: go-fmt
- id: go-lint
- id: go-unit-tests

View File

@ -1,19 +1,5 @@
/*
Microsub server
Copyright (C) 2018 Peter Stuifzand
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Package main contains the main command for the Microsub server.
*/
package main
@ -77,7 +63,7 @@ func WithAuth(handler http.Handler, b *memoryBackend) http.Handler {
return
}
if token.Me != b.Me {
if token.Me != b.Me { // FIXME: Me should be part of the request
log.Printf("Missing \"me\" in token response: %#v\n", token)
http.Error(w, "Wrong me", 403)
return

View File

@ -1,19 +1,20 @@
/*
Microsub server
Copyright (C) 2018 Peter Stuifzand
Package main runs the microsub server
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Copyright (C) 2018 Peter Stuifzand
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package main
@ -42,6 +43,7 @@ import (
"willnorris.com/go/microformats"
)
// DefaultPrio is the priority value for new channels
const DefaultPrio = 9999999
type memoryBackend struct {
@ -51,10 +53,10 @@ type memoryBackend struct {
Channels map[string]microsub.Channel
Feeds map[string][]microsub.Feed
Settings map[string]channelSetting
NextUid int
NextUID int
Me string
TokenEndpoint string
Me string // FIXME: should be removed
TokenEndpoint string // FIXME: should be removed
AuthEnabled bool
ticker *time.Ticker
@ -68,6 +70,7 @@ type channelSetting struct {
IncludeRegex string
}
// Debug interface for easy of use in other packages
type Debug interface {
Debug()
}
@ -176,7 +179,8 @@ func createMemoryBackend() {
backend.Channels[c.UID] = c
}
backend.NextUid = 1000000
backend.NextUID = 1000000
// FIXME: can't be used in Backend
backend.Me = "https://example.com/"
backend.lock.Unlock()
@ -443,24 +447,24 @@ func (b *memoryBackend) Search(query string) ([]microsub.Feed, error) {
}
defer resp.Body.Close()
fetchUrl, err := url.Parse(u)
md := microformats.Parse(resp.Body, fetchUrl)
fetchURL, err := url.Parse(u)
md := microformats.Parse(resp.Body, fetchURL)
if err != nil {
log.Printf("Error while fetching %s: %v\n", u, err)
continue
}
feedResp, err := Fetch2(fetchUrl.String())
feedResp, err := Fetch2(fetchURL.String())
if err != nil {
log.Printf("Error in fetch of %s - %v\n", fetchUrl, err)
log.Printf("Error in fetch of %s - %v\n", fetchURL, err)
continue
}
defer feedResp.Body.Close()
// TODO: Combine FeedHeader and FeedItems so we can use it here
parsedFeed, err := fetch.FeedHeader(&fetch2{}, fetchUrl.String(), feedResp.Header.Get("Content-Type"), feedResp.Body)
parsedFeed, err := fetch.FeedHeader(&fetch2{}, fetchURL.String(), feedResp.Header.Get("Content-Type"), feedResp.Body)
if err != nil {
log.Printf("Error in parse of %s - %v\n", fetchUrl, err)
log.Printf("Error in parse of %s - %v\n", fetchURL, err)
continue
}
@ -706,7 +710,7 @@ func Fetch2(fetchURL string) (*http.Response, error) {
client := http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("fetch failed: %s", u, err)
return nil, fmt.Errorf("fetch failed: %s: %s", u, err)
}
defer resp.Body.Close()
@ -724,10 +728,11 @@ func Fetch2(fetchURL string) (*http.Response, error) {
}
func (b *memoryBackend) createChannel(name string) microsub.Channel {
uid := fmt.Sprintf("%012d", b.NextUid)
uid := fmt.Sprintf("%012d", b.NextUID)
channel := microsub.Channel{
UID: uid,
Name: name,
UID: uid,
Name: name,
Unread: microsub.Unread{microsub.UnreadCount, false, 0},
}
return channel
}
@ -737,7 +742,7 @@ func (b *memoryBackend) setChannel(channel microsub.Channel) {
defer b.lock.Unlock()
b.Channels[channel.UID] = channel
b.Feeds[channel.UID] = []microsub.Feed{}
b.NextUid++
b.NextUID++
}
func updateChannelInRedis(conn redis.Conn, uid string, prio int) {

View File

@ -291,8 +291,10 @@ func (timeline *redisStreamTimeline) Items(before, after string) (microsub.Timel
}
return microsub.Timeline{
Items: items,
Paging: microsub.Pagination{},
Items: items,
Paging: microsub.Pagination{
After: items[len(items)-1].ID,
},
}, nil
}

View File

@ -13,6 +13,7 @@ import (
"p83.nl/go/ekster/pkg/microsub"
)
// Client is a HTTP client for Microsub
type Client struct {
Me *url.URL
MicrosubEndpoint *url.URL
@ -120,6 +121,7 @@ func (c *Client) microsubPostFormRequest(action string, args map[string]string,
return res, err
}
// ChannelsGetList gets the channels from a Microsub server
func (c *Client) ChannelsGetList() ([]microsub.Channel, error) {
args := make(map[string]string)
res, err := c.microsubGetRequest("channels", args)
@ -146,6 +148,7 @@ func (c *Client) ChannelsGetList() ([]microsub.Channel, error) {
return channels.Channels, err
}
// TimelineGet gets a timeline from a Microsub server
func (c *Client) TimelineGet(before, after, channel string) (microsub.Timeline, error) {
args := make(map[string]string)
args["after"] = after
@ -172,6 +175,7 @@ func (c *Client) TimelineGet(before, after, channel string) (microsub.Timeline,
return timeline, nil
}
// PreviewURL gets a Timeline for a url from a Microsub server
func (c *Client) PreviewURL(url string) (microsub.Timeline, error) {
args := make(map[string]string)
args["url"] = url
@ -338,7 +342,3 @@ func (c *Client) MarkRead(channel string, uids []string) error {
res.Body.Close()
return nil
}
func (c *Client) AddEventListener(el microsub.EventListener) error {
panic("implement me")
}

View File

@ -1,21 +1,3 @@
/*
Microsub server
Copyright (C) 2018 Peter Stuifzand
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Package microsub describes the protocol methods of the Microsub protocol
package microsub
@ -34,11 +16,13 @@ import (
block / unblock
*/
// Constants for Unread
const (
UnreadBool = 0
UnreadCount = 1
)
// Unread is a special int/bool value for the JSON response
type Unread struct {
Type int
Unread bool

View File

@ -0,0 +1,84 @@
package microsub
import (
"encoding/json"
"testing"
"github.com/stretchr/testify/assert"
)
func Test_UnmarshalUnreadBool(t *testing.T) {
var x Unread
err := json.Unmarshal([]byte("false"), &x)
if assert.NoError(t, err) {
assert.Equal(t, UnreadBool, x.Type)
assert.False(t, x.Unread)
}
}
func Test_UnmarshalUnreadBoolTrue(t *testing.T) {
var x Unread
err := json.Unmarshal([]byte("true"), &x)
if assert.NoError(t, err) {
assert.Equal(t, UnreadBool, x.Type)
assert.True(t, x.Unread)
}
}
func Test_UnmarshalUnreadIntZero(t *testing.T) {
var x Unread
err := json.Unmarshal([]byte("0"), &x)
if assert.NoError(t, err) {
assert.Equal(t, UnreadCount, x.Type)
assert.Equal(t, 0, x.UnreadCount)
}
}
func Test_UnmarshalUnreadIntNonZero(t *testing.T) {
var x Unread
err := json.Unmarshal([]byte("209449"), &x)
if assert.NoError(t, err) {
assert.Equal(t, UnreadCount, x.Type)
assert.Equal(t, 209449, x.UnreadCount)
}
}
func Test_MarshalUnreadEmpty(t *testing.T) {
x := Unread{}
bytes, err := json.Marshal(x)
if assert.NoError(t, err) {
assert.Equal(t, "false", string(bytes))
}
}
func Test_MarshalUnreadBoolFalse(t *testing.T) {
x := Unread{Type: UnreadBool, Unread: false}
bytes, err := json.Marshal(x)
if assert.NoError(t, err) {
assert.Equal(t, "false", string(bytes))
}
}
func Test_MarshalUnreadBoolTrue(t *testing.T) {
x := Unread{Type: UnreadBool, Unread: true}
bytes, err := json.Marshal(x)
if assert.NoError(t, err) {
assert.Equal(t, "true", string(bytes))
}
}
func Test_MarshalUnreadIntZero(t *testing.T) {
x := Unread{Type: UnreadCount, UnreadCount: 0}
bytes, err := json.Marshal(x)
if assert.NoError(t, err) {
assert.Equal(t, "0", string(bytes))
}
}
func Test_MarshalUnreadIntNonZero(t *testing.T) {
x := Unread{Type: UnreadCount, UnreadCount: 1884844}
bytes, err := json.Marshal(x)
if assert.NoError(t, err) {
assert.Equal(t, "1884844", string(bytes))
}
}

View File

@ -1,19 +1,6 @@
/*
ekster - microsub server
Copyright (C) 2018 Peter Stuifzand
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Package server contains the microsub server itself. It implements http.Handler.
It follows the spec at https://indieweb.org/Microsub-spec.
*/
package server
@ -31,6 +18,7 @@ var (
entryRegex = regexp.MustCompile("^entry\\[\\d+\\]$")
)
// Constants used for the responses
const (
OutputContentType = "application/json; charset=utf-8"
)
@ -51,11 +39,14 @@ func respondJSON(w http.ResponseWriter, value interface{}) {
}
}
// NewMicrosubHandler is the main entry point for the microsub server
// It returns a handler for HTTP and a broker that will send events.
func NewMicrosubHandler(backend microsub.Microsub) (http.Handler, *Broker) {
broker := NewServer()
return &microsubHandler{backend, broker}, broker
}
// Methods required by http.Handler
func (h *microsubHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
r.ParseForm()

View File

@ -14,7 +14,7 @@ import (
func createServerClient() (*httptest.Server, *client.Client) {
backend := &NullBackend{}
handler := NewMicrosubHandler(backend)
handler, _ := NewMicrosubHandler(backend)
server := httptest.NewServer(handler)

View File

@ -25,10 +25,6 @@ import (
type NullBackend struct {
}
func (b *NullBackend) AddEventListener(el microsub.EventListener) error {
panic("implement me")
}
// ChannelsGetList gets no channels
func (b *NullBackend) ChannelsGetList() ([]microsub.Channel, error) {
return []microsub.Channel{
@ -66,26 +62,31 @@ func (b *NullBackend) TimelineGet(before, after, channel string) (microsub.Timel
}, nil
}
// FollowGetList implements the follow list command
func (b *NullBackend) FollowGetList(uid string) ([]microsub.Feed, error) {
return []microsub.Feed{
{Name: "test", Type: "feed", URL: "https://example.com/"},
}, nil
}
// FollowURL follows a new url
func (b *NullBackend) FollowURL(uid string, url string) (microsub.Feed, error) {
return microsub.Feed{Type: "feed", URL: url}, nil
}
// UnfollowURL unfollows a url
func (b *NullBackend) UnfollowURL(uid string, url string) error {
return nil
}
// Search search for a query and return an example list of feeds
func (b *NullBackend) Search(query string) ([]microsub.Feed, error) {
return []microsub.Feed{
{"feed", "https://example.com/", "Example", "test.jpg", "test", microsub.Card{}},
}, nil
}
// PreviewURL shows an empty feed
func (b *NullBackend) PreviewURL(url string) (microsub.Timeline, error) {
return microsub.Timeline{
Paging: microsub.Pagination{},
@ -93,6 +94,7 @@ func (b *NullBackend) PreviewURL(url string) (microsub.Timeline, error) {
}, nil
}
// MarkRead marks no items as read
func (b *NullBackend) MarkRead(channel string, uids []string) error {
return nil
}