<commit_before>package api2go

import (
	"database/sql"
	"encoding/json"
	"errors"
	"gopkg.in/guregu/null.v2/zero"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

type Magic struct {
	ID MagicID
}

type MagicID string

func (m MagicID) String() string {
	return "This should be visible"
}

var _ = Describe("Marshalling", func() {
	type SimplePost struct {
		Title, Text string
	}

	type Comment struct {
		ID   int
		Text string
	}

	type Author struct {
		ID       int
		Name     string
		Password string `json:"-"`
	}

	type Post struct {
		ID          int
		Title       string
		Comments    []Comment
		CommentsIDs []int
		Author      *Author
		AuthorID    sql.NullInt64
	}

	Context("When marshaling simple objects", func() {
		var (
			firstPost, secondPost       SimplePost
			firstPostMap, secondPostMap map[string]interface{}
		)

		BeforeEach(func() {
			firstPost = SimplePost{Title: "First Post", Text: "Lipsum"}
			firstPostMap = map[string]interface{}{
				"title": firstPost.Title,
				"text":  firstPost.Text,
			}
			secondPost = SimplePost{Title: "Second Post", Text: "Getting more advanced!"}
			secondPostMap = map[string]interface{}{
				"title": secondPost.Title,
				"text":  secondPost.Text,
			}
		})

		It("marshals single object", func() {
			i, err := Marshal(firstPost)
			Expect(err).To(BeNil())
			Expect(i).To(Equal(map[string]interface{}{
				"simplePosts": []interface{}{
					firstPostMap,
				},
			}))
		})

		It("should prefer fmt.Stringer().String() over string contents", func() {
			m := Magic{}
			m.ID = "This should be only internal"

			expected := map[string]interface{}{
				"magics": []interface{}{
					map[string]interface{}{
						"id": "This should be visible"}}}

			v, e := Marshal(m)
			Expect(e).ToNot(HaveOccurred())
			Expect(v).To(Equal(expected))
		})

		It("marshal nil value", func() {
			_, err := Marshal(nil)
			Expect(err).To(HaveOccurred())
		})

		It("marshals collections object", func() {
			i, err := Marshal([]SimplePost{firstPost, secondPost})
			Expect(err).To(BeNil())
			Expect(i).To(Equal(map[string]interface{}{
				"simplePosts": []interface{}{
					firstPostMap,
					secondPostMap,
				},
			}))
		})

		It("marshals empty collections", func() {
			i, err := Marshal([]SimplePost{})
			Expect(err).To(BeNil())
			Expect(i).To(Equal(map[string]interface{}{
				"simplePosts": []interface{}{},
			}))
		})

		It("returns an error when passing interface{} slices", func() {
			_, err := Marshal([]interface{}{})
			Expect(err).To(HaveOccurred())
		})

		It("returns an error when passing an empty string", func() {
			_, err := Marshal("")
			Expect(err).To(HaveOccurred())
		})

		It("marshals to JSON", func() {
			j, err := MarshalToJSON([]SimplePost{firstPost})
			Expect(err).To(BeNil())
			var m map[string]interface{}
			Expect(json.Unmarshal(j, &m)).To(BeNil())
			Expect(m).To(Equal(map[string]interface{}{
				"simplePosts": []interface{}{
					firstPostMap,
				},
			}))
		})

		Context("when converting IDs to string", func() {
			It("leaves string", func() {
				type StringID struct{ ID string }
				i, err := Marshal(StringID{ID: "1"})
				Expect(err).To(BeNil())
				Expect(i).To(Equal(map[string]interface{}{
					"stringIDs": []interface{}{
						map[string]interface{}{
							"id": "1",
						},
					},
				}))
			})

			It("converts ints", func() {
				type IntID struct{ ID int }
				i, err := Marshal(IntID{ID: 1})
				Expect(err).To(BeNil())
				Expect(i).To(Equal(map[string]interface{}{
					"intIDs": []interface{}{
						map[string]interface{}{
							"id": "1",
						},
					},
				}))
			})

			It("converts uints", func() {
				type UintID struct{ ID uint }
				i, err := Marshal(UintID{ID: 1})
				Expect(err).To(BeNil())
				Expect(i).To(Equal(map[string]interface{}{
					"uintIDs": []interface{}{
						map[string]interface{}{
							"id": "1",
						},
					},
				}))
			})
		})
	})

	Context("When marshaling compound objects", func() {
		It("marshals nested objects", func() {
			comment1 := Comment{ID: 1, Text: "First!"}
			comment2 := Comment{ID: 2, Text: "Second!"}
			author := Author{ID: 1, Name: "Test Author"}
			post1 := Post{ID: 1, Title: "Foobar", Comments: []Comment{comment1, comment2}, Author: &author}
			post2 := Post{ID: 2, Title: "Foobarbarbar", Comments: []Comment{comment1, comment2}, Author: &author}

			posts := []Post{post1, post2}

			i, err := Marshal(posts)
			Expect(err).To(BeNil())
			Expect(i).To(Equal(map[string]interface{}{
				"posts": []interface{}{
					map[string]interface{}{
						"id":    "1",
						"title": "Foobar",
						"links": map[string]interface{}{
							"comments": []interface{}{"1", "2"},
							"author":   "1",
						},
					},
					map[string]interface{}{
						"id":    "2",
						"title": "Foobarbarbar",
						"links": map[string]interface{}{
							"comments": []interface{}{"1", "2"},
							"author":   "1",
						},
					},
				},
				"linked": map[string][]interface{}{
					"comments": []interface{}{
						map[string]interface{}{
							"id":   "1",
							"text": "First!",
						},
						map[string]interface{}{
							"id":   "2",
							"text": "Second!",
						},
					},
					"authors": []interface{}{
						map[string]interface{}{
							"id":   "1",
							"name": "Test Author",
						},
					},
				},
			}))
		})

		It("adds IDs", func() {
			post := Post{ID: 1, Comments: []Comment{}, CommentsIDs: []int{1}}
			i, err := Marshal(post)
			Expect(err).To(BeNil())
			Expect(i).To(Equal(map[string]interface{}{
				"posts": []interface{}{
					map[string]interface{}{
						"id":    "1",
						"title": "",
						"links": map[string]interface{}{
							"comments": []interface{}{"1"},
							"author":   nil,
						},
					},
				},
			}))
		})

		It("prefers nested structs when given both, structs and IDs", func() {
			comment := Comment{ID: 1}
			author := Author{ID: 1, Name: "Tester"}
			post := Post{ID: 1, Comments: []Comment{comment}, CommentsIDs: []int{2}, Author: &author, AuthorID: sql.NullInt64{Int64: 1337}}
			i, err := Marshal(post)
			Expect(err).To(BeNil())
			Expect(i).To(Equal(map[string]interface{}{
				"posts": []interface{}{
					map[string]interface{}{
						"id":    "1",
						"title": "",
						"links": map[string]interface{}{
							"comments": []interface{}{"1"},
							"author":   "1",
						},
					},
				},
				"linked": map[string][]interface{}{
					"comments": []interface{}{
						map[string]interface{}{
							"id":   "1",
							"text": "",
						},
					},
					"authors": []interface{}{
						map[string]interface{}{
							"id":   "1",
							"name": "Tester",
						},
					},
				},
			}))
		})

		It("uses ID field if single relation struct is nil", func() {
			type AnotherPost struct {
				ID       int
				AuthorID int
				Author   *Author
			}

			anotherPost := AnotherPost{ID: 1, AuthorID: 1}
			i, err := Marshal(anotherPost)
			Expect(err).To(BeNil())
			Expect(i).To(Equal(map[string]interface{}{
				"anotherPosts": []interface{}{
					map[string]interface{}{
						"id": "1",
						"links": map[string]interface{}{
							"author": "1",
						},
					},
				},
			}))
		})

		It("uses ID field for the sql.NullInt64 type", func() {
			type SqlTypesPost struct {
				ID       int
				AuthorID sql.NullInt64
				Author   *Author
			}

			anotherPost := SqlTypesPost{ID: 1, AuthorID: sql.NullInt64{1, true}}
			i, err := Marshal(anotherPost)
			Expect(err).To(BeNil())
			Expect(i).To(Equal(map[string]interface{}{
				"sqlTypesPosts": []interface{}{
					map[string]interface{}{
						"id": "1",
						"links": map[string]interface{}{
							"author": "1",
						},
					},
				},
			}))
		})

		It("uses ID field for the sql.NullString type", func() {
			type SqlTypesPost struct {
				ID       int
				AuthorID sql.NullString
				Author   *Author
			}

			anotherPost := SqlTypesPost{ID: 1, AuthorID: sql.NullString{"1", true}}
			i, err := Marshal(anotherPost)
			Expect(err).To(BeNil())
			Expect(i).To(Equal(map[string]interface{}{
				"sqlTypesPosts": []interface{}{
					map[string]interface{}{
						"id": "1",
						"links": map[string]interface{}{
							"author": "1",
						},
					},
				},
			}))
		})

		It("returns an error if ID field but no struct field is in struct", func() {
			type WrongStruct struct {
				ID       int
				AuthorID int
			}

			wrongStruct := WrongStruct{ID: 1, AuthorID: 1}
			_, err := Marshal(wrongStruct)
			Expect(err).To(Equal(errors.New("expected struct to have field Author")))
		})
	})

	Context("when marshalling zero value types", func() {
		type ZeroPost struct {
			ID    string
			Title string
			Value zero.Float
		}

		type ZeroPostPointer struct {
			ID    string
			Title string
			Value *zero.Float
		}

		theFloat := zero.NewFloat(2.3, true)
		post := ZeroPost{ID: "1", Title: "test", Value: theFloat}
		pointerPost := ZeroPostPointer{ID: "1", Title: "test", Value: &theFloat}

		It("correctly unmarshals driver values", func() {
			postMap := map[string]interface{}{
				"zeroPosts": []interface{}{
					map[string]interface{}{
						"id":    "1",
						"title": "test",
						"value": theFloat,
					},
				},
			}

			marshalled, err := Marshal(post)

			Expect(err).To(BeNil())
			Expect(marshalled).To(Equal(postMap))
		})

		It("correctly unmarshals into json", func() {
			expectedJSON := `{"zeroPosts":[{"id":"1","title":"test","value":2.3}]}`

			json, err := MarshalToJSON(post)
			Expect(err).To(BeNil())
			Expect(string(json)).To(Equal(expectedJSON))
		})

		It("correctly unmarshals driver values with pointer", func() {
			postMap := map[string]interface{}{
				"zeroPostPointers": []interface{}{
					map[string]interface{}{
						"id":    "1",
						"title": "test",
						"value": &theFloat,
					},
				},
			}

			marshalled, err := Marshal(pointerPost)

			Expect(err).To(BeNil())
			Expect(marshalled).To(BeEquivalentTo(postMap))
		})

		It("correctly unmarshals with pointer into json", func() {
			expectedJSON := `{"zeroPostPointers":[{"id":"1","title":"test","value":2.3}]}`

			json, err := MarshalToJSON(pointerPost)
			Expect(err).To(BeNil())
			Expect(string(json)).To(Equal(expectedJSON))
		})
	})

	Context("When marshalling objects linking to other instances of the same type", func() {
		type Question struct {
			ID                  string
			Text                string
			InspiringQuestionID sql.NullString
			InspiringQuestion   *Question
		}

		question1 := Question{ID: "1", Text: "Does this test work?"}
		question2 := Question{ID: "2", Text: "Will it ever work?", InspiringQuestionID: sql.NullString{"1", true}, InspiringQuestion: &question1}

		It("Correctly marshalls question1 and sets question 2 into linked", func() {
			expected := map[string]interface{}{
				"questions": []interface{}{
					map[string]interface{}{
						"id":   "2",
						"text": "Will it ever work?",
						"links": map[string]interface{}{
							"inspiringQuestion": "1",
						},
					},
				},
				"linked": map[string][]interface{}{
					"questions": []interface{}{
						map[string]interface{}{
							"id":   "1",
							"text": "Does this test work?",
							"links": map[string]interface{}{
								"inspiringQuestion": nil,
							},
						},
					},
				},
			}

			marshalled, err := Marshal(question2)
			Expect(err).To(BeNil())
			Expect(marshalled).To(BeEquivalentTo(expected))
		})
	})
})
<commit_msg>test if duplicate linked structs are marshalled once<commit_after>package api2go

import (
	"database/sql"
	"encoding/json"
	"errors"
	"gopkg.in/guregu/null.v2/zero"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

type Magic struct {
	ID MagicID
}

type MagicID string

func (m MagicID) String() string {
	return "This should be visible"
}

var _ = Describe("Marshalling", func() {
	type SimplePost struct {
		Title, Text string
	}

	type Comment struct {
		ID   int
		Text string
	}

	type Author struct {
		ID       int
		Name     string
		Password string `json:"-"`
	}

	type Post struct {
		ID          int
		Title       string
		Comments    []Comment
		CommentsIDs []int
		Author      *Author
		AuthorID    sql.NullInt64
	}

	Context("When marshaling simple objects", func() {
		var (
			firstPost, secondPost       SimplePost
			firstPostMap, secondPostMap map[string]interface{}
		)

		BeforeEach(func() {
			firstPost = SimplePost{Title: "First Post", Text: "Lipsum"}
			firstPostMap = map[string]interface{}{
				"title": firstPost.Title,
				"text":  firstPost.Text,
			}
			secondPost = SimplePost{Title: "Second Post", Text: "Getting more advanced!"}
			secondPostMap = map[string]interface{}{
				"title": secondPost.Title,
				"text":  secondPost.Text,
			}
		})

		It("marshals single object", func() {
			i, err := Marshal(firstPost)
			Expect(err).To(BeNil())
			Expect(i).To(Equal(map[string]interface{}{
				"simplePosts": []interface{}{
					firstPostMap,
				},
			}))
		})

		It("should prefer fmt.Stringer().String() over string contents", func() {
			m := Magic{}
			m.ID = "This should be only internal"

			expected := map[string]interface{}{
				"magics": []interface{}{
					map[string]interface{}{
						"id": "This should be visible"}}}

			v, e := Marshal(m)
			Expect(e).ToNot(HaveOccurred())
			Expect(v).To(Equal(expected))
		})

		It("marshal nil value", func() {
			_, err := Marshal(nil)
			Expect(err).To(HaveOccurred())
		})

		It("marshals collections object", func() {
			i, err := Marshal([]SimplePost{firstPost, secondPost})
			Expect(err).To(BeNil())
			Expect(i).To(Equal(map[string]interface{}{
				"simplePosts": []interface{}{
					firstPostMap,
					secondPostMap,
				},
			}))
		})

		It("marshals empty collections", func() {
			i, err := Marshal([]SimplePost{})
			Expect(err).To(BeNil())
			Expect(i).To(Equal(map[string]interface{}{
				"simplePosts": []interface{}{},
			}))
		})

		It("returns an error when passing interface{} slices", func() {
			_, err := Marshal([]interface{}{})
			Expect(err).To(HaveOccurred())
		})

		It("returns an error when passing an empty string", func() {
			_, err := Marshal("")
			Expect(err).To(HaveOccurred())
		})

		It("marshals to JSON", func() {
			j, err := MarshalToJSON([]SimplePost{firstPost})
			Expect(err).To(BeNil())
			var m map[string]interface{}
			Expect(json.Unmarshal(j, &m)).To(BeNil())
			Expect(m).To(Equal(map[string]interface{}{
				"simplePosts": []interface{}{
					firstPostMap,
				},
			}))
		})

		Context("when converting IDs to string", func() {
			It("leaves string", func() {
				type StringID struct{ ID string }
				i, err := Marshal(StringID{ID: "1"})
				Expect(err).To(BeNil())
				Expect(i).To(Equal(map[string]interface{}{
					"stringIDs": []interface{}{
						map[string]interface{}{
							"id": "1",
						},
					},
				}))
			})

			It("converts ints", func() {
				type IntID struct{ ID int }
				i, err := Marshal(IntID{ID: 1})
				Expect(err).To(BeNil())
				Expect(i).To(Equal(map[string]interface{}{
					"intIDs": []interface{}{
						map[string]interface{}{
							"id": "1",
						},
					},
				}))
			})

			It("converts uints", func() {
				type UintID struct{ ID uint }
				i, err := Marshal(UintID{ID: 1})
				Expect(err).To(BeNil())
				Expect(i).To(Equal(map[string]interface{}{
					"uintIDs": []interface{}{
						map[string]interface{}{
							"id": "1",
						},
					},
				}))
			})
		})
	})

	Context("When marshaling compound objects", func() {
		It("marshals nested objects", func() {
			comment1 := Comment{ID: 1, Text: "First!"}
			comment2 := Comment{ID: 2, Text: "Second!"}
			author := Author{ID: 1, Name: "Test Author"}
			post1 := Post{ID: 1, Title: "Foobar", Comments: []Comment{comment1, comment2}, Author: &author}
			post2 := Post{ID: 2, Title: "Foobarbarbar", Comments: []Comment{comment1, comment2}, Author: &author}

			posts := []Post{post1, post2}

			i, err := Marshal(posts)
			Expect(err).To(BeNil())
			Expect(i).To(Equal(map[string]interface{}{
				"posts": []interface{}{
					map[string]interface{}{
						"id":    "1",
						"title": "Foobar",
						"links": map[string]interface{}{
							"comments": []interface{}{"1", "2"},
							"author":   "1",
						},
					},
					map[string]interface{}{
						"id":    "2",
						"title": "Foobarbarbar",
						"links": map[string]interface{}{
							"comments": []interface{}{"1", "2"},
							"author":   "1",
						},
					},
				},
				"linked": map[string][]interface{}{
					"comments": []interface{}{
						map[string]interface{}{
							"id":   "1",
							"text": "First!",
						},
						map[string]interface{}{
							"id":   "2",
							"text": "Second!",
						},
					},
					"authors": []interface{}{
						map[string]interface{}{
							"id":   "1",
							"name": "Test Author",
						},
					},
				},
			}))
		})

		It("adds IDs", func() {
			post := Post{ID: 1, Comments: []Comment{}, CommentsIDs: []int{1}}
			i, err := Marshal(post)
			Expect(err).To(BeNil())
			Expect(i).To(Equal(map[string]interface{}{
				"posts": []interface{}{
					map[string]interface{}{
						"id":    "1",
						"title": "",
						"links": map[string]interface{}{
							"comments": []interface{}{"1"},
							"author":   nil,
						},
					},
				},
			}))
		})

		It("prefers nested structs when given both, structs and IDs", func() {
			comment := Comment{ID: 1}
			author := Author{ID: 1, Name: "Tester"}
			post := Post{ID: 1, Comments: []Comment{comment}, CommentsIDs: []int{2}, Author: &author, AuthorID: sql.NullInt64{Int64: 1337}}
			i, err := Marshal(post)
			Expect(err).To(BeNil())
			Expect(i).To(Equal(map[string]interface{}{
				"posts": []interface{}{
					map[string]interface{}{
						"id":    "1",
						"title": "",
						"links": map[string]interface{}{
							"comments": []interface{}{"1"},
							"author":   "1",
						},
					},
				},
				"linked": map[string][]interface{}{
					"comments": []interface{}{
						map[string]interface{}{
							"id":   "1",
							"text": "",
						},
					},
					"authors": []interface{}{
						map[string]interface{}{
							"id":   "1",
							"name": "Tester",
						},
					},
				},
			}))
		})

		It("uses ID field if single relation struct is nil", func() {
			type AnotherPost struct {
				ID       int
				AuthorID int
				Author   *Author
			}

			anotherPost := AnotherPost{ID: 1, AuthorID: 1}
			i, err := Marshal(anotherPost)
			Expect(err).To(BeNil())
			Expect(i).To(Equal(map[string]interface{}{
				"anotherPosts": []interface{}{
					map[string]interface{}{
						"id": "1",
						"links": map[string]interface{}{
							"author": "1",
						},
					},
				},
			}))
		})

		It("uses ID field for the sql.NullInt64 type", func() {
			type SqlTypesPost struct {
				ID       int
				AuthorID sql.NullInt64
				Author   *Author
			}

			anotherPost := SqlTypesPost{ID: 1, AuthorID: sql.NullInt64{1, true}}
			i, err := Marshal(anotherPost)
			Expect(err).To(BeNil())
			Expect(i).To(Equal(map[string]interface{}{
				"sqlTypesPosts": []interface{}{
					map[string]interface{}{
						"id": "1",
						"links": map[string]interface{}{
							"author": "1",
						},
					},
				},
			}))
		})

		It("uses ID field for the sql.NullString type", func() {
			type SqlTypesPost struct {
				ID       int
				AuthorID sql.NullString
				Author   *Author
			}

			anotherPost := SqlTypesPost{ID: 1, AuthorID: sql.NullString{"1", true}}
			i, err := Marshal(anotherPost)
			Expect(err).To(BeNil())
			Expect(i).To(Equal(map[string]interface{}{
				"sqlTypesPosts": []interface{}{
					map[string]interface{}{
						"id": "1",
						"links": map[string]interface{}{
							"author": "1",
						},
					},
				},
			}))
		})

		It("returns an error if ID field but no struct field is in struct", func() {
			type WrongStruct struct {
				ID       int
				AuthorID int
			}

			wrongStruct := WrongStruct{ID: 1, AuthorID: 1}
			_, err := Marshal(wrongStruct)
			Expect(err).To(Equal(errors.New("expected struct to have field Author")))
		})
	})

	Context("when marshalling zero value types", func() {
		type ZeroPost struct {
			ID    string
			Title string
			Value zero.Float
		}

		type ZeroPostPointer struct {
			ID    string
			Title string
			Value *zero.Float
		}

		theFloat := zero.NewFloat(2.3, true)
		post := ZeroPost{ID: "1", Title: "test", Value: theFloat}
		pointerPost := ZeroPostPointer{ID: "1", Title: "test", Value: &theFloat}

		It("correctly unmarshals driver values", func() {
			postMap := map[string]interface{}{
				"zeroPosts": []interface{}{
					map[string]interface{}{
						"id":    "1",
						"title": "test",
						"value": theFloat,
					},
				},
			}

			marshalled, err := Marshal(post)

			Expect(err).To(BeNil())
			Expect(marshalled).To(Equal(postMap))
		})

		It("correctly unmarshals into json", func() {
			expectedJSON := `{"zeroPosts":[{"id":"1","title":"test","value":2.3}]}`

			json, err := MarshalToJSON(post)
			Expect(err).To(BeNil())
			Expect(string(json)).To(Equal(expectedJSON))
		})

		It("correctly unmarshals driver values with pointer", func() {
			postMap := map[string]interface{}{
				"zeroPostPointers": []interface{}{
					map[string]interface{}{
						"id":    "1",
						"title": "test",
						"value": &theFloat,
					},
				},
			}

			marshalled, err := Marshal(pointerPost)

			Expect(err).To(BeNil())
			Expect(marshalled).To(BeEquivalentTo(postMap))
		})

		It("correctly unmarshals with pointer into json", func() {
			expectedJSON := `{"zeroPostPointers":[{"id":"1","title":"test","value":2.3}]}`

			json, err := MarshalToJSON(pointerPost)
			Expect(err).To(BeNil())
			Expect(string(json)).To(Equal(expectedJSON))
		})
	})

	Context("When marshalling objects linking to other instances of the same type", func() {
		type Question struct {
			ID                  string
			Text                string
			InspiringQuestionID sql.NullString
			InspiringQuestion   *Question
		}

		question1 := Question{ID: "1", Text: "Does this test work?"}
		question1Duplicate := Question{ID: "1", Text: "Does this test work?"}
		question2 := Question{ID: "2", Text: "Will it ever work?", InspiringQuestionID: sql.NullString{"1", true}, InspiringQuestion: &question1}
		question3 := Question{ID: "3", Text: "It works now", InspiringQuestionID: sql.NullString{"1", true}, InspiringQuestion: &question1Duplicate}

		It("Correctly marshalls question1 and sets question 2 into linked", func() {
			expected := map[string]interface{}{
				"questions": []interface{}{
					map[string]interface{}{
						"id":   "2",
						"text": "Will it ever work?",
						"links": map[string]interface{}{
							"inspiringQuestion": "1",
						},
					},
				},
				"linked": map[string][]interface{}{
					"questions": []interface{}{
						map[string]interface{}{
							"id":   "1",
							"text": "Does this test work?",
							"links": map[string]interface{}{
								"inspiringQuestion": nil,
							},
						},
					},
				},
			}

			marshalled, err := Marshal(question2)
			Expect(err).To(BeNil())
			Expect(marshalled).To(BeEquivalentTo(expected))
		})

		It("Does not marshall same dependencies multiple times", func() {
			expected := map[string]interface{}{
				"questions": []interface{}{
					map[string]interface{}{
						"id":   "3",
						"text": "It works now",
						"links": map[string]interface{}{
							"inspiringQuestion": "1",
						},
					},
					map[string]interface{}{
						"id":   "2",
						"text": "Will it ever work?",
						"links": map[string]interface{}{
							"inspiringQuestion": "1",
						},
					},
				},
				"linked": map[string][]interface{}{
					"questions": []interface{}{
						map[string]interface{}{
							"id":   "1",
							"text": "Does this test work?",
							"links": map[string]interface{}{
								"inspiringQuestion": nil,
							},
						},
					},
				},
			}

			marshalled, err := Marshal([]Question{question3, question2})
			Expect(err).To(BeNil())
			Expect(marshalled).To(BeEquivalentTo(expected))
		})
	})
})
<|endoftext|>


<commit_before>package forms

import (
	"github.com/kirves/revel-forms/fields"
	"html/template"
	"reflect"
	"strings"
)

const (
	POST = "POST"
	GET  = "GET"
)

type Form struct {
	fields   []fields.FieldInterface
	fieldMap map[string]int
	style    string
	template *template.Template
	class    []string
	id       string
	params   map[string]string
	css      map[string]string
	method   string
	action   string
}

func BaseForm(method, action string) *Form {
	tmpl, err := template.ParseFiles("templates/baseform.html")
	if err != nil {
		panic(err)
	}
	return &Form{
		make([]fields.FieldInterface, 0),
		make(map[string]int),
		fields.BASE,
		tmpl,
		[]string{},
		"",
		map[string]string{},
		map[string]string{},
		method,
		action,
	}
}

func BootstrapForm(method, action string) *Form {
	tmpl, err := template.ParseFiles("templates/bootstrapform.html")
	if err != nil {
		panic(err)
	}
	return &Form{
		make([]fields.FieldInterface, 0),
		make(map[string]int),
		fields.BOOTSTRAP,
		tmpl,
		[]string{},
		"",
		map[string]string{},
		map[string]string{},
		method,
		action,
	}
}

func BaseFormFromModel(m interface{}, method, action string) *Form {
	form := BaseForm(method, action)
	for _, v := range unWindStructure(m, "") {
		form.AddField(v)
	}
	form.AddField(fields.SubmitButton("submit", "Submit"))
	return form
}

func unWindStructure(m interface{}, baseName string) []fields.FieldInterface {
	t := reflect.TypeOf(m)
	fieldList := make([]fields.FieldInterface, 0)
	for i := 0; i < t.NumField(); i++ {
		tag := t.Field(i).Tag.Get("form_skip")
		if tag == "" {
			tag = t.Field(i).Tag.Get("form_widget")
			var f fields.FieldInterface
			var fName string
			if baseName == "" {
				fName = t.Field(i).Name
			} else {
				fName = strings.Join([]string{baseName, t.Field(i).Name}, ".")
			}
			switch tag {
			case "text":
				f = fields.TextField(fName)
			case "textarea":
				f = fields.TextAreaField(fName, 30, 50)
			case "password":
				f = fields.PasswordField(fName)
			case "date":
			case "datetime":
			case "time":
			case "number":
			case "range":
			default:
				switch t.Field(i).Type.String() {
				case "string":
					f = fields.TextField(fName)
				case "bool":
					f = fields.Checkbox(fName, false)
				case "time.Time":
					f = fields.TextField(fName) // FIX
				case "int":
					f = fields.TextField(fName) // FIX
				case "struct":
					fieldList = append(fieldList, unWindStructure(reflect.New(t.Field(i).Type).Elem().Interface(), fName)...)
					f = nil
				default:
					f = fields.TextField(fName)
				}
			}
			if f != nil {
				f.SetLabel(strings.Title(t.Field(i).Name))
				fieldList = append(fieldList, f)
			}
		}
	}
	return fieldList
}
<commit_msg>Bool and select defaults<commit_after>package forms

import (
	"github.com/kirves/revel-forms/fields"
	"html/template"
	"reflect"
	"strings"
)

const (
	POST = "POST"
	GET  = "GET"
)

type Form struct {
	fields   []fields.FieldInterface
	fieldMap map[string]int
	style    string
	template *template.Template
	class    []string
	id       string
	params   map[string]string
	css      map[string]string
	method   string
	action   string
}

func BaseForm(method, action string) *Form {
	tmpl, err := template.ParseFiles("templates/baseform.html")
	if err != nil {
		panic(err)
	}
	return &Form{
		make([]fields.FieldInterface, 0),
		make(map[string]int),
		fields.BASE,
		tmpl,
		[]string{},
		"",
		map[string]string{},
		map[string]string{},
		method,
		action,
	}
}

func BootstrapForm(method, action string) *Form {
	tmpl, err := template.ParseFiles("templates/bootstrapform.html")
	if err != nil {
		panic(err)
	}
	return &Form{
		make([]fields.FieldInterface, 0),
		make(map[string]int),
		fields.BOOTSTRAP,
		tmpl,
		[]string{},
		"",
		map[string]string{},
		map[string]string{},
		method,
		action,
	}
}

func BaseFormFromModel(m interface{}, method, action string) *Form {
	form := BaseForm(method, action)
	for _, v := range unWindStructure(m, "") {
		form.AddField(v)
	}
	form.AddField(fields.SubmitButton("submit", "Submit"))
	return form
}

func unWindStructure(m interface{}, baseName string) []fields.FieldInterface {
	t := reflect.TypeOf(m)
	fieldList := make([]fields.FieldInterface, 0)
	for i := 0; i < t.NumField(); i++ {
		tag := t.Field(i).Tag.Get("form_skip")
		if tag == "" {
			tag = t.Field(i).Tag.Get("form_widget")
			var f fields.FieldInterface
			var fName string
			if baseName == "" {
				fName = t.Field(i).Name
			} else {
				fName = strings.Join([]string{baseName, t.Field(i).Name}, ".")
			}
			switch tag {
			case "text":
				f = fields.TextField(fName)
			case "textarea":
				f = fields.TextAreaField(fName, 30, 50)
			case "password":
				f = fields.PasswordField(fName)
			case "select":
				choices := strings.Split(t.Field(i).Tag.Get("form_choices"), "|")
				if len(choices)%2 != 0 {
					f = nil
					break
				}
				chMap := make(map[string]string)
				for i := 0; i < len(choices)-1; i += 2 {
					chMap[choices[i]] = choices[i+1]
				}
				f = fields.SelectField(fName, chMap)
			case "date":
			case "datetime":
			case "time":
			case "number":
			case "range":
			default:
				switch t.Field(i).Type.String() {
				case "string":
					f = fields.TextField(fName)
				case "bool":
					initVal := t.Field(i).Tag.Get("form_checked")
					if initVal != "" {
						f = fields.Checkbox(fName, true)
					} else {
						f = fields.Checkbox(fName, false)
					}
				case "time.Time":
					f = fields.TextField(fName) // FIX
				case "int":
					f = fields.TextField(fName) // FIX
				case "struct":
					fieldList = append(fieldList, unWindStructure(reflect.New(t.Field(i).Type).Elem().Interface(), fName)...)
					f = nil
				default:
					f = fields.TextField(fName)
				}
			}
			if f != nil {
				f.SetLabel(strings.Title(t.Field(i).Name))
				fieldList = append(fieldList, f)
			}
		}
	}
	return fieldList
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	_ "github.com/lib/pq"
	"os"
	"strconv"
	"time"
)

func dbConnect(retriesLeft int) error {
	con := os.Getenv("POSTGRES")
	logger.Infof("opening connection to postgres: %s", con)

	var err error
	db, err = sql.Open("postgres", con)
	if err != nil {
		logger.Errorf("cannot open connection to postgres: %v", err)
		return err
	}

	err = db.Ping()
	if err != nil {
		if retriesLeft > 0 {
			logger.Errorf("cannot talk to postgres, retrying in 10 seconds (%d attempts left): %v", retriesLeft-1, err)
			time.Sleep(10 * time.Second)
			return dbConnect(retriesLeft - 1)
		} else {
			logger.Errorf("cannot talk to postgres, last attempt failed: %v", err)
			return err
		}
	}

	statement := `
		CREATE TABLE IF NOT EXISTS migrations (
			filename TEXT NOT NULL UNIQUE
		);
	`
	_, err = db.Exec(statement)
	if err != nil {
		logger.Errorf("cannot create migrations table: %v", err)
		return err
	}

	maxIdleConnections, err := strconv.Atoi(os.Getenv("MAX_IDLE_PG_CONNECTIONS"))
	if err != nil {
		logger.Warningf("cannot parse COMMENTO_MAX_IDLE_PG_CONNECTIONS: %v", err)
		maxIdleConnections = 50
	}

	db.SetMaxIdleConns(maxIdleConnections)

	return nil
}
<commit_msg>database_connect.go: redact password before log message<commit_after>package main

import (
	"database/sql"
	"net/url"
	_ "github.com/lib/pq"
	"os"
	"strconv"
	"time"
)

func dbConnect(retriesLeft int) error {
	con := os.Getenv("POSTGRES")
	u, err := url.Parse(con)
	if err != nil {
		logger.Errorf("invalid postgres connection URI: %v", err)
		return err
	}
	u.User = url.UserPassword(u.User.Username(), "redacted")
	logger.Infof("opening connection to postgres: %s", u.String())

	db, err = sql.Open("postgres", con)
	if err != nil {
		logger.Errorf("cannot open connection to postgres: %v", err)
		return err
	}

	err = db.Ping()
	if err != nil {
		if retriesLeft > 0 {
			logger.Errorf("cannot talk to postgres, retrying in 10 seconds (%d attempts left): %v", retriesLeft-1, err)
			time.Sleep(10 * time.Second)
			return dbConnect(retriesLeft - 1)
		} else {
			logger.Errorf("cannot talk to postgres, last attempt failed: %v", err)
			return err
		}
	}

	statement := `
		CREATE TABLE IF NOT EXISTS migrations (
			filename TEXT NOT NULL UNIQUE
		);
	`
	_, err = db.Exec(statement)
	if err != nil {
		logger.Errorf("cannot create migrations table: %v", err)
		return err
	}

	maxIdleConnections, err := strconv.Atoi(os.Getenv("MAX_IDLE_PG_CONNECTIONS"))
	if err != nil {
		logger.Warningf("cannot parse COMMENTO_MAX_IDLE_PG_CONNECTIONS: %v", err)
		maxIdleConnections = 50
	}

	db.SetMaxIdleConns(maxIdleConnections)

	return nil
}
<|endoftext|>


<commit_before>//file is borrowed from github.com/kelseyhightower/confd

package main

import (
	"encoding/json"
	"errors"
	"os"
	"path"
	"strconv"
	"strings"
	"time"

	"github.com/fatih/structs"
)

func newFuncMap() map[string]interface{} {
	m := make(map[string]interface{})
	m["base"] = path.Base
	m["split"] = strings.Split
	m["json"] = UnmarshalJsonObject
	m["jsonArray"] = UnmarshalJsonArray
	m["dir"] = path.Dir
	m["getenv"] = os.Getenv
	m["join"] = strings.Join
	m["atoi"] = strconv.Atoi
	m["where"] = where
	m["datetime"] = time.Now
	m["toUpper"] = strings.ToUpper
	m["toLower"] = strings.ToLower
	m["contains"] = strings.Contains
	m["replace"] = strings.Replace
	return m
}

////////////////////////////////////////////////////////////////////////////////
func where(m []interface{}, sliceKey string, sliceVal interface{}) ([]interface{}, error) {
	ret := make([]interface{}, 0)
	if m == nil {
		return ret, errors.New("where: source is nil")
	}
	if sliceKey == "" {
		return ret, errors.New("where: key is nil")
	}
	if sliceVal == nil {
		return ret, errors.New("where: value is nil")
	}

	for _, str := range m {
		st := structs.New(str)
		field := st.Field(sliceKey)
		if field.Value() == sliceVal {
			ret = append(ret, str)
		}
	}

	return ret, nil
}

func addFuncs(out, in map[string]interface{}) {
	for name, fn := range in {
		out[name] = fn
	}
}

func UnmarshalJsonObject(data string) (map[string]interface{}, error) {
	var ret map[string]interface{}
	err := json.Unmarshal([]byte(data), &ret)
	return ret, err
}

func UnmarshalJsonArray(data string) ([]interface{}, error) {
	var ret []interface{}
	err := json.Unmarshal([]byte(data), &ret)
	return ret, err
}
<commit_msg>autopush@1446218643<commit_after>//file is borrowed from github.com/kelseyhightower/confd

package main

import (
	"encoding/json"
	"errors"
	"os"
	"path"
	"strconv"
	"strings"
	"time"

	"github.com/fatih/structs"
)

func newFuncMap() map[string]interface{} {
	m := make(map[string]interface{})
	m["base"] = path.Base
	m["split"] = strings.Split
	m["json"] = UnmarshalJsonObject
	m["jsonArray"] = UnmarshalJsonArray
	m["dir"] = path.Dir
	m["getenv"] = os.Getenv
	m["join"] = strings.Join
	m["atoi"] = strconv.Atoi
	m["where"] = where
	m["datetime"] = time.Now
	m["toUpper"] = strings.ToUpper
	m["toLower"] = strings.ToLower
	m["contains"] = strings.Contains
	m["replace"] = strings.Replace
	return m
}

////////////////////////////////////////////////////////////////////////////////
func where(in interface{}, sliceKey string, sliceVal interface{}) ([]interface{}, error) {
	ret := make([]interface{}, 0)
	if in == nil {
		return ret, errors.New("where: source is nil")
	}
	if sliceKey == "" {
		return ret, errors.New("where: key is nil")
	}
	if sliceVal == nil {
		return ret, errors.New("where: value is nil")
	}

	m := in.([]interface{})

	for _, str := range m {
		st := structs.New(str)
		field := st.Field(sliceKey)
		if field.Value() == sliceVal {
			ret = append(ret, str)
		}
	}

	return ret, nil
}

func addFuncs(out, in map[string]interface{}) {
	for name, fn := range in {
		out[name] = fn
	}
}

func UnmarshalJsonObject(data string) (map[string]interface{}, error) {
	var ret map[string]interface{}
	err := json.Unmarshal([]byte(data), &ret)
	return ret, err
}

func UnmarshalJsonArray(data string) ([]interface{}, error) {
	var ret []interface{}
	err := json.Unmarshal([]byte(data), &ret)
	return ret, err
}
<|endoftext|>


<commit_before>package glope

import (
	"fmt"
	"log"
	"math"
)

type Cluster struct {
	id           int
	n            int            //Number of transactions
	w            int            //Number of unique items
	s            int            //Total number of items
	occ          map[string]int //Item to item count map
	Transactions []*Transaction
}

type Transaction struct {
	cluster         *Cluster
	clusterPosition int //Position of transaction inside cluster
	Instance        interface{}
	Items           []string
}

//Calculate a profit using this formula: number of items/(number of unique items ** repulsion)
func getProfit(s, w int, r float64) float64 {
	return float64(s) / math.Pow(float64(w), r)
}

func newCluster(id int, trans *Transaction) *Cluster {
	items_len := len(trans.Items)
	c := &Cluster{
		id:           id,
		occ:          make(map[string]int, items_len),
		s:            items_len,
		w:            items_len,
		n:            1,
		Transactions: []*Transaction{trans},
	}
	for _, item := range trans.Items {
		c.occ[item] = 1
	}
	trans.cluster = c
	return c
}

func (c *Cluster) String() string {
	return fmt.Sprintf("[Cluster %d]", c.id)
}

//Calculates a profit of adding transaction items to given cluster
func (c *Cluster) getItemsProfit(items []string, r float64) float64 {
	if c.n == 0 {
		s := len(items)
		return getProfit(s, s, r)
	} else {
		sNew := c.s + len(items)
		wNew := c.w
		for _, item := range items {
			if _, found := c.occ[item]; !found {
				wNew++
			}
		}
		return getProfit(sNew*(c.n+1), wNew, r) - getProfit(c.s*c.n, c.w, r)
	}
}

func (c *Cluster) addItem(item string) {
	val, found := c.occ[item]
	if !found {
		c.occ[item] = 1
	} else {
		c.occ[item] = val + 1
	}
}

func (c *Cluster) removeItem(item string) {
	val, found := c.occ[item]
	if !found {
		return
	}
	if val == 1 {
		delete(c.occ, item)
	}
	c.occ[item] -= 1
}

func (c *Cluster) addTransaction(trans *Transaction) {
	for _, item := range trans.Items {
		c.addItem(item)
	}
	c.s += len(trans.Items)
	c.w = len(c.occ)
	c.n++
	trans.clusterPosition = len(c.Transactions)
	c.Transactions = append(c.Transactions, trans)
	trans.cluster = c
}

func (c *Cluster) removeTransaction(trans *Transaction) {
	for _, item := range trans.Items {
		c.removeItem(item)
	}
	c.s -= len(trans.Items)
	c.w = len(c.occ)
	c.n--
	c.Transactions[trans.clusterPosition] = nil
}

func (c *Cluster) clearNilTransactions() {
	nonNilTransactions := make([]*Transaction, 0)
	for _, transaction := range c.Transactions {
		if transaction != nil {
			nonNilTransactions = append(nonNilTransactions, transaction)
		}
	}
	c.Transactions = nonNilTransactions
}

func Clusterize(data []*Transaction, repulsion float64) []*Cluster {
	if repulsion == 0 {
		repulsion = 4.0 // default value
	}
	var clusters []*Cluster
	log.Print("Initializing clusters")
	for _, transaction := range data {
		clusters = addTransactionToBestCluster(clusters, transaction, repulsion)
	}
	log.Printf("Init finished, created %d clusters", len(clusters))
	log.Print("Moving transactions to best clusters")
	for i := 1; ; i++ {
		log.Printf("move %d", i)
		moved := false
		for _, transaction := range data {
			originalClusterId := transaction.cluster.id
			transaction.cluster.removeTransaction(transaction)
			clusters = addTransactionToBestCluster(clusters, transaction, repulsion)
			if transaction.cluster.id != originalClusterId {
				moved = true
			}
		}
		if !moved {
			break
		}
	}
	log.Print("Finished, cleaning empty clusters")
	notEmptyClusters := make([]*Cluster, 0)
	for _, cluster := range clusters {
		if cluster.n > 0 {
			cluster.clearNilTransactions()
			notEmptyClusters = append(notEmptyClusters, cluster)
		}
	}
	log.Printf("Cleaning finished, returning %d clusters", len(notEmptyClusters))
	return notEmptyClusters
}

func addTransactionToBestCluster(clusters []*Cluster, transaction *Transaction, repulsion float64) []*Cluster {
	if len(clusters) > 0 {
		tempS := len(transaction.Items)
		profitMax := getProfit(tempS, tempS, repulsion)

		var bestCluster *Cluster
		var bestProfit float64

		for _, cluster := range clusters {
			clusterProfit := cluster.getItemsProfit(transaction.Items, repulsion)
			if clusterProfit > bestProfit {
				if clusterProfit > profitMax {
					cluster.addTransaction(transaction)
					return clusters
				} else {
					bestCluster = cluster
					bestProfit = clusterProfit
				}
			}
		}
		if bestProfit >= profitMax {
			bestCluster.addTransaction(transaction)
			return clusters
		}
	}
	return append(clusters, newCluster(len(clusters), transaction))
}
<commit_msg>removed debug logging, added some docs<commit_after>package glope

import (
	"fmt"
	"math"
)

type Cluster struct {
	id           int
	n            int            //Number of transactions
	w            int            //Number of unique items
	s            int            //Total number of items
	occ          map[string]int //Item to item count map
	Transactions []*Transaction
}

type Transaction struct {
	cluster         *Cluster
	clusterPosition int //Position of transaction inside cluster
	Instance        interface{}
	Items           []string
}

//Calculate a profit using this formula: number of items/(number of unique items ** repulsion)
func getProfit(s, w int, r float64) float64 {
	return float64(s) / math.Pow(float64(w), r)
}

func newCluster(id int, trans *Transaction) *Cluster {
	items_len := len(trans.Items)
	c := &Cluster{
		id:           id,
		occ:          make(map[string]int, items_len),
		s:            items_len,
		w:            items_len,
		n:            1,
		Transactions: []*Transaction{trans},
	}
	for _, item := range trans.Items {
		c.occ[item] = 1
	}
	trans.cluster = c
	return c
}

func (c *Cluster) String() string {
	return fmt.Sprintf("[Cluster %d]", c.id)
}

//Calculates a profit of adding transaction items to given cluster
func (c *Cluster) getItemsProfit(items []string, r float64) float64 {
	if c.n == 0 {
		s := len(items)
		return getProfit(s, s, r)
	} else {
		sNew := c.s + len(items)
		wNew := c.w
		for _, item := range items {
			if _, found := c.occ[item]; !found {
				wNew++
			}
		}
		return getProfit(sNew*(c.n+1), wNew, r) - getProfit(c.s*c.n, c.w, r)
	}
}

//Adds an item of a transaction to the cluster
func (c *Cluster) addItem(item string) {
	val, found := c.occ[item]
	if !found {
		c.occ[item] = 1
	} else {
		c.occ[item] = val + 1
	}
}

//Removes an item of a transaction from the cluster
func (c *Cluster) removeItem(item string) {
	val, found := c.occ[item]
	if !found {
		return
	}
	if val == 1 {
		delete(c.occ, item)
	}
	c.occ[item] -= 1
}

func (c *Cluster) addTransaction(trans *Transaction) {
	for _, item := range trans.Items {
		c.addItem(item)
	}
	c.s += len(trans.Items)
	c.w = len(c.occ)
	c.n++
	trans.clusterPosition = len(c.Transactions)
	c.Transactions = append(c.Transactions, trans)
	trans.cluster = c
}

func (c *Cluster) removeTransaction(trans *Transaction) {
	for _, item := range trans.Items {
		c.removeItem(item)
	}
	c.s -= len(trans.Items)
	c.w = len(c.occ)
	c.n--
	c.Transactions[trans.clusterPosition] = nil
}

func (c *Cluster) clearNilTransactions() {
	nonNilTransactions := make([]*Transaction, 0)
	for _, transaction := range c.Transactions {
		if transaction != nil {
			nonNilTransactions = append(nonNilTransactions, transaction)
		}
	}
	c.Transactions = nonNilTransactions
}

//Clusterizes given transactions
func Clusterize(data []*Transaction, repulsion float64) []*Cluster {
	if repulsion == 0 {
		repulsion = 4.0 // default value
	}
	var clusters []*Cluster
	for _, transaction := range data {
		clusters = addTransactionToBestCluster(clusters, transaction, repulsion)
	}
	for {
		moved := false
		for _, transaction := range data {
			originalClusterId := transaction.cluster.id
			transaction.cluster.removeTransaction(transaction)
			clusters = addTransactionToBestCluster(clusters, transaction, repulsion)
			if transaction.cluster.id != originalClusterId {
				moved = true
			}
		}
		if !moved {
			break
		}
	}
	notEmptyClusters := make([]*Cluster, 0)
	for _, cluster := range clusters {
		if cluster.n > 0 {
			cluster.clearNilTransactions()
			notEmptyClusters = append(notEmptyClusters, cluster)
		}
	}
	return notEmptyClusters
}

func addTransactionToBestCluster(clusters []*Cluster, transaction *Transaction, repulsion float64) []*Cluster {
	if len(clusters) > 0 {
		tempS := len(transaction.Items)
		profitMax := getProfit(tempS, tempS, repulsion)

		var bestCluster *Cluster
		var bestProfit float64

		for _, cluster := range clusters {
			clusterProfit := cluster.getItemsProfit(transaction.Items, repulsion)
			if clusterProfit > bestProfit {
				if clusterProfit > profitMax {
					cluster.addTransaction(transaction)
					return clusters
				} else {
					bestCluster = cluster
					bestProfit = clusterProfit
				}
			}
		}
		if bestProfit >= profitMax {
			bestCluster.addTransaction(transaction)
			return clusters
		}
	}
	return append(clusters, newCluster(len(clusters), transaction))
}
<|endoftext|>


<commit_before>package godbg

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"os"
	"regexp"
	"runtime/debug"
	"strings"
)

// http://stackoverflow.com/a/23554672/6309 https://vividcortex.com/blog/2013/12/03/go-idiom-package-and-object/
// you design a type with methods as usual, and then you also place matching functions at the package level itself.
// These functions simply delegate to a default instance of the type that’s a private package-level variable, created in an init() function.

// Pdbg allows to print debug message with indent and function name added
type Pdbg struct {
	bout   *bytes.Buffer
	berr   *bytes.Buffer
	sout   *bufio.Writer
	serr   *bufio.Writer
	breaks []string
}

// Out returns a writer for normal messages.
// By default, os.StdOut
func Out() io.Writer {
	return pdbg.Out()
}

// Out returns a writer for normal messages for a given pdbg instance.
// By default, os.StdOut
func (pdbg *Pdbg) Out() io.Writer {
	if pdbg.sout == nil {
		return os.Stdout
	}
	return pdbg.sout
}

// Err returns a writer for error messages.
// By default, os.StdErr
func Err() io.Writer {
	return pdbg.Err()
}

// Err returns a writer for error messages for a given pdbg instance.
// By default, os.StdErr
func (pdbg *Pdbg) Err() io.Writer {
	if pdbg.serr == nil {
		return os.Stderr
	}
	return pdbg.serr
}

// global pdbg used for printing
var pdbg = NewPdbg()

// Option set an option for a Pdbg
// http://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis
type Option func(*Pdbg)

// SetBuffers is an option for replacing stdout and stderr by
// bytes buffers (in a bufio.Writer).
// If apdbg is nil, set for the global pdbg instance
func SetBuffers(apdbg *Pdbg) {
	if apdbg == nil {
		apdbg = pdbg
	}
	apdbg.bout = bytes.NewBuffer(nil)
	apdbg.sout = bufio.NewWriter(apdbg.bout)
	apdbg.berr = bytes.NewBuffer(nil)
	apdbg.serr = bufio.NewWriter(apdbg.berr)
}

// NewPdbg creates a PDbg instance, with options
func NewPdbg(options ...Option) *Pdbg {
	newpdbg := &Pdbg{}
	for _, option := range options {
		option(newpdbg)
	}
	newpdbg.breaks = append(newpdbg.breaks, "smartystreets")
	return newpdbg
}

// ResetIOs reset the out and err buffer of global pdbg instance
func ResetIOs() {
	pdbg.ResetIOs()
}

// ResetIOs reset the out and err buffer
// (unless they were the default stdout and stderr,
// in which case it does nothing)
func (pdbg *Pdbg) ResetIOs() {
	if pdbg.sout != nil {
		pdbg.bout = bytes.NewBuffer(nil)
		pdbg.sout.Reset(pdbg.bout)
		pdbg.berr = bytes.NewBuffer(nil)
		pdbg.serr.Reset(pdbg.berr)
	}
}

// OutString returns the string for out messages for the global pdbg instance.
// It flushes the out buffer.
// If out is set to os.Stdout, returns an empty string
func OutString() string {
	return pdbg.OutString()
}

// OutString returns the string for out messages for a given pdbg instance.
// It flushes the out buffer.
// If out is set to os.Stdout, returns an empty string
func (pdbg *Pdbg) OutString() string {
	if pdbg.sout == nil {
		return ""
	}
	pdbg.sout.Flush()
	return pdbg.bout.String()
}

// ErrString returns the string for error messages for the global pdbg instance.
// It flushes the err buffer.
// If err is set to os.StdErr, returns an empty string
func ErrString() string {
	return pdbg.ErrString()
}

// ErrString returns the string for error messages for a given pdbg instance.
// It flushes the err buffer.
// If err is set to os.StdErr, returns an empty string
func (pdbg *Pdbg) ErrString() string {
	if pdbg.serr == nil {
		return ""
	}
	pdbg.serr.Flush()
	return pdbg.berr.String()
}

// For instance: github.com/VonC/godbg/_test/_obj_test/gogdb.go:174 (0x44711b)
var rxDbgLine, _ = regexp.Compile(`^.*\.go:(\d+)\s`)
var rxDbgFnct, _ = regexp.Compile(`^\s+(?:.*?\(([^\)]+)\))?\.?([^:]+)`)

func pdbgInc(scanner *bufio.Scanner, dbgLine string) string {
	scanner.Scan()
	line := scanner.Text()
	mf := rxDbgFnct.FindSubmatchIndex([]byte(line))
	// fmt.Printf("lineF '%v', mf '%+v'\n", line, mf)
	/*if len(mf) == 0 {
		return ""
	}*/
	dbgFnct := ""
	if mf[2] > -1 {
		dbgFnct = line[mf[2]:mf[3]]
	}
	if dbgFnct != "" {
		dbgFnct = dbgFnct + "."
	}
	dbgFnct = dbgFnct + line[mf[4]:mf[5]]

	return dbgFnct + ":" + dbgLine
}

func pdbgExcluded(dbg string) bool {
	if strings.Contains(dbg, "ReadConfig:") {
		return true
	}
	return false
}

func (pdbg *Pdbg) pdbgBreak(dbg string) bool {
	for _, b := range pdbg.breaks {
		if strings.Contains(dbg, b) {
			return true
		}
	}
	return false
}

// Pdbgf uses global Pdbg variable for printing strings, with indent and function name
func Pdbgf(format string, args ...interface{}) string {
	return pdbg.Pdbgf(format, args...)
}

// Pdbgf uses custom Pdbg variable for printing strings, with indent and function name
func (pdbg *Pdbg) Pdbgf(format string, args ...interface{}) string {
	msg := fmt.Sprintf(format+"\n", args...)
	msg = strings.TrimSpace(msg)
	bstack := bytes.NewBuffer(debug.Stack())
	// fmt.Printf("%+v\n", bstack)

	scanner := bufio.NewScanner(bstack)
	pmsg := ""
	depth := 0
	for scanner.Scan() {
		line := scanner.Text()
		if strings.Contains(line, "/_obj_test/") {
			depth = 1
			continue
		}
		if pdbg.pdbgBreak(line) {
			break
		}
		m := rxDbgLine.FindSubmatchIndex([]byte(line))
		// fmt.Printf("'%s' (%s) => '%+v'\n", line, rxDbgLine.String(), m)
		/*if len(m) == 0 {
			continue
		}*/
		if depth > 0 && depth < 4 {
			dbg := pdbgInc(scanner, line[m[2]:m[3]])
			if dbg == "" {
				continue
			}
			if depth == 1 {
				if pdbgExcluded(dbg) {
					return ""
				}
				pmsg = "[" + dbg + "]"
			} else {
				pmsg = pmsg + " (" + dbg + ")"
			}
		}
		depth = depth + 1
	}
	spaces := ""
	if depth >= 2 {
		spaces = strings.Repeat(" ", depth-2)
	}
	// fmt.Printf("spaces '%s', depth '%d'\n", spaces, depth)
	res := pmsg
	pmsg = spaces + pmsg
	msg = pmsg + "\n" + spaces + "  " + msg + "\n"
	// fmt.Printf("MSG '%v'\n", msg)
	fmt.Fprint(pdbg.Err(), fmt.Sprint(msg))
	return res
}
<commit_msg>Implement SetExcludes() and option<commit_after>package godbg

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"os"
	"regexp"
	"runtime/debug"
	"strings"
)

// http://stackoverflow.com/a/23554672/6309 https://vividcortex.com/blog/2013/12/03/go-idiom-package-and-object/
// you design a type with methods as usual, and then you also place matching functions at the package level itself.
// These functions simply delegate to a default instance of the type that’s a private package-level variable, created in an init() function.

// Pdbg allows to print debug message with indent and function name added
type Pdbg struct {
	bout     *bytes.Buffer
	berr     *bytes.Buffer
	sout     *bufio.Writer
	serr     *bufio.Writer
	breaks   []string
	excludes []string
}

// Out returns a writer for normal messages.
// By default, os.StdOut
func Out() io.Writer {
	return pdbg.Out()
}

// Out returns a writer for normal messages for a given pdbg instance.
// By default, os.StdOut
func (pdbg *Pdbg) Out() io.Writer {
	if pdbg.sout == nil {
		return os.Stdout
	}
	return pdbg.sout
}

// Err returns a writer for error messages.
// By default, os.StdErr
func Err() io.Writer {
	return pdbg.Err()
}

// Err returns a writer for error messages for a given pdbg instance.
// By default, os.StdErr
func (pdbg *Pdbg) Err() io.Writer {
	if pdbg.serr == nil {
		return os.Stderr
	}
	return pdbg.serr
}

// global pdbg used for printing
var pdbg = NewPdbg()

// Option set an option for a Pdbg
// http://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis
type Option func(*Pdbg)

// SetBuffers is an option for replacing stdout and stderr by
// bytes buffers (in a bufio.Writer).
// If apdbg is nil, set for the global pdbg instance
func SetBuffers(apdbg *Pdbg) {
	if apdbg == nil {
		apdbg = pdbg
	}
	apdbg.bout = bytes.NewBuffer(nil)
	apdbg.sout = bufio.NewWriter(apdbg.bout)
	apdbg.berr = bytes.NewBuffer(nil)
	apdbg.serr = bufio.NewWriter(apdbg.berr)
}

// SetExcludes set excludes on a pdbg (nil for global pdbg)
func (apdbg *Pdbg) SetExcludes(excludes []string) {
	apdbg.excludes = excludes
}

// OptExcludes is an option to set excludes at the creation of a pdbg
func OptExcludes(apdbg *Pdbg, excludes []string) func(*Pdbg) {
	if apdbg == nil {
		apdbg = pdbg
	}
	return func(apdbg *Pdbg) {
		apdbg.SetExcludes(excludes)
	}
}

// NewPdbg creates a PDbg instance, with options
func NewPdbg(options ...Option) *Pdbg {
	newpdbg := &Pdbg{}
	for _, option := range options {
		option(newpdbg)
	}
	newpdbg.breaks = append(newpdbg.breaks, "smartystreets")
	return newpdbg
}

// ResetIOs reset the out and err buffer of global pdbg instance
func ResetIOs() {
	pdbg.ResetIOs()
}

// ResetIOs reset the out and err buffer
// (unless they were the default stdout and stderr,
// in which case it does nothing)
func (pdbg *Pdbg) ResetIOs() {
	if pdbg.sout != nil {
		pdbg.bout = bytes.NewBuffer(nil)
		pdbg.sout.Reset(pdbg.bout)
		pdbg.berr = bytes.NewBuffer(nil)
		pdbg.serr.Reset(pdbg.berr)
	}
}

// OutString returns the string for out messages for the global pdbg instance.
// It flushes the out buffer.
// If out is set to os.Stdout, returns an empty string
func OutString() string {
	return pdbg.OutString()
}

// OutString returns the string for out messages for a given pdbg instance.
// It flushes the out buffer.
// If out is set to os.Stdout, returns an empty string
func (pdbg *Pdbg) OutString() string {
	if pdbg.sout == nil {
		return ""
	}
	pdbg.sout.Flush()
	return pdbg.bout.String()
}

// ErrString returns the string for error messages for the global pdbg instance.
// It flushes the err buffer.
// If err is set to os.StdErr, returns an empty string
func ErrString() string {
	return pdbg.ErrString()
}

// ErrString returns the string for error messages for a given pdbg instance.
// It flushes the err buffer.
// If err is set to os.StdErr, returns an empty string
func (pdbg *Pdbg) ErrString() string {
	if pdbg.serr == nil {
		return ""
	}
	pdbg.serr.Flush()
	return pdbg.berr.String()
}

// For instance: github.com/VonC/godbg/_test/_obj_test/gogdb.go:174 (0x44711b)
var rxDbgLine, _ = regexp.Compile(`^.*\.go:(\d+)\s`)
var rxDbgFnct, _ = regexp.Compile(`^\s+(?:.*?\(([^\)]+)\))?\.?([^:]+)`)

func pdbgInc(scanner *bufio.Scanner, dbgLine string) string {
	scanner.Scan()
	line := scanner.Text()
	mf := rxDbgFnct.FindSubmatchIndex([]byte(line))
	// fmt.Printf("lineF '%v', mf '%+v'\n", line, mf)
	/*if len(mf) == 0 {
		return ""
	}*/
	dbgFnct := ""
	if mf[2] > -1 {
		dbgFnct = line[mf[2]:mf[3]]
	}
	if dbgFnct != "" {
		dbgFnct = dbgFnct + "."
	}
	dbgFnct = dbgFnct + line[mf[4]:mf[5]]

	return dbgFnct + ":" + dbgLine
}

func pdbgExcluded(dbg string) bool {
	for _, e := range pdbg.excludes {
		if strings.Contains(dbg, e) {
			return true
		}
	}
	return false
}

func (pdbg *Pdbg) pdbgBreak(dbg string) bool {
	for _, b := range pdbg.breaks {
		if strings.Contains(dbg, b) {
			return true
		}
	}
	return false
}

// Pdbgf uses global Pdbg variable for printing strings, with indent and function name
func Pdbgf(format string, args ...interface{}) string {
	return pdbg.Pdbgf(format, args...)
}

// Pdbgf uses custom Pdbg variable for printing strings, with indent and function name
func (pdbg *Pdbg) Pdbgf(format string, args ...interface{}) string {
	msg := fmt.Sprintf(format+"\n", args...)
	msg = strings.TrimSpace(msg)
	bstack := bytes.NewBuffer(debug.Stack())
	// fmt.Printf("%+v\n", bstack)

	scanner := bufio.NewScanner(bstack)
	pmsg := ""
	depth := 0
	for scanner.Scan() {
		line := scanner.Text()
		if strings.Contains(line, "/_obj_test/") {
			depth = 1
			continue
		}
		if pdbg.pdbgBreak(line) {
			break
		}
		m := rxDbgLine.FindSubmatchIndex([]byte(line))
		// fmt.Printf("'%s' (%s) => '%+v'\n", line, rxDbgLine.String(), m)
		/*if len(m) == 0 {
			continue
		}*/
		if depth > 0 && depth < 4 {
			dbg := pdbgInc(scanner, line[m[2]:m[3]])
			if dbg == "" {
				continue
			}
			if depth == 1 {
				if pdbgExcluded(dbg) {
					return ""
				}
				pmsg = "[" + dbg + "]"
			} else {
				pmsg = pmsg + " (" + dbg + ")"
			}
		}
		depth = depth + 1
	}
	spaces := ""
	if depth >= 2 {
		spaces = strings.Repeat(" ", depth-2)
	}
	// fmt.Printf("spaces '%s', depth '%d'\n", spaces, depth)
	res := pmsg
	pmsg = spaces + pmsg
	msg = pmsg + "\n" + spaces + "  " + msg + "\n"
	// fmt.Printf("MSG '%v'\n", msg)
	fmt.Fprint(pdbg.Err(), fmt.Sprint(msg))
	return res
}
<|endoftext|>


<commit_before>/*
Package gorbl lets you perform RBL (Real-time Blackhole List - https://en.wikipedia.org/wiki/DNSBL) lookups using Golang

This package takes inspiration from a similar module that I wrote in Python
(https://github.com/polera/rblwatch).

gorbl takes a simpler approach:  Basic lookup capability is provided by the
lib, while, unlike in rblwatch, concurrent lookups and the lists on which to
search are left to those using the lib.

JSON annotations on the types are provided as a convenience.
*/
package gorbl

import (
	"fmt"
	"net"
	"strings"
)

/*
RBLResults holds the results of the lookup.
*/
type RBLResults struct {
	// List is the RBL that was searched
	List string `json:"list"`
	// Host is the host or IP that was passed (i.e. smtp.gmail.com)
	Host string `json:"host"`
	// Results is a slice of Results - one per IP address searched
	Results []Result `json:"results"`
}

/*
Result holds the individual IP lookup results for each RBL search
*/
type Result struct {
	// Address is the IP address that was searched
	Address string `json:"address"`
	// Listed indicates whether or not the IP was on the RBL
	Listed bool `json:"listed"`
	// RBL lists sometimes add extra information as a TXT record
	// if any info is present, it will be stored here.
	Text string `json:"text"`
	// Error represents any error that was encountered (DNS timeout, host not
	// found, etc.) if any
	Error bool `json:"error"`
	// ErrorType is the type of error encountered if any
	ErrorType error `json:"error_type"`
}

/*
Reverse the octets of a given IPv4 address
64.233.171.108 becomes 108.171.233.64
*/
func Reverse(ip net.IP) string {
	if ip.To4() != nil {
		splitAddress := strings.Split(ip.String(), ".")

		for i, j := 0, len(splitAddress)-1; i < len(splitAddress)/2; i, j = i+1, j-1 {
			splitAddress[i], splitAddress[j] = splitAddress[j], splitAddress[i]
		}

		return strings.Join(splitAddress, ".")
	}
	return ""
}

func query(rbl string, host string, r *Result) {
	//	r := Result{}
	r.Listed = false

	lookup := fmt.Sprintf("%s.%s", host, rbl)

	res, err := net.LookupHost(lookup)
	if len(res) > 0 {
		r.Listed = true
		txt, _ := net.LookupTXT(lookup)
		if len(txt) > 0 {
			r.Text = txt[0]
		}
	}
	if err != nil {
		r.Error = true
		r.ErrorType = err
	}

	return
}

/*
Lookup performs the search and returns the RBLResults
*/
func Lookup(rblList string, targetHost string) (r RBLResults) {
	r.List = rblList
	r.Host = targetHost

	if ip, err := net.LookupIP(targetHost); err == nil {
		for _, addr := range ip {
			if addr.To4() != nil {
				res := Result{}
				res.Address = addr.String()

				addr := Reverse(addr)

				query(rblList, addr, &res)

				r.Results = append(r.Results, res)

			}
		}
	}
	return
}
<commit_msg>Formatting<commit_after>/*
Package gorbl lets you perform RBL (Real-time Blackhole List - https://en.wikipedia.org/wiki/DNSBL)
lookups using Golang

This package takes inspiration from a similar module that I wrote in Python
(https://github.com/polera/rblwatch).

gorbl takes a simpler approach:  Basic lookup capability is provided by the
lib.  Unlike in rblwatch, concurrent lookups and the lists to search are
left to those using the lib.

JSON annotations on the types are provided as a convenience.
*/
package gorbl

import (
	"fmt"
	"net"
	"strings"
)

/*
RBLResults holds the results of the lookup.
*/
type RBLResults struct {
	// List is the RBL that was searched
	List string `json:"list"`
	// Host is the host or IP that was passed (i.e. smtp.gmail.com)
	Host string `json:"host"`
	// Results is a slice of Results - one per IP address searched
	Results []Result `json:"results"`
}

/*
Result holds the individual IP lookup results for each RBL search
*/
type Result struct {
	// Address is the IP address that was searched
	Address string `json:"address"`
	// Listed indicates whether or not the IP was on the RBL
	Listed bool `json:"listed"`
	// RBL lists sometimes add extra information as a TXT record
	// if any info is present, it will be stored here.
	Text string `json:"text"`
	// Error represents any error that was encountered (DNS timeout, host not
	// found, etc.) if any
	Error bool `json:"error"`
	// ErrorType is the type of error encountered if any
	ErrorType error `json:"error_type"`
}

/*
Reverse the octets of a given IPv4 address
64.233.171.108 becomes 108.171.233.64
*/
func Reverse(ip net.IP) string {
	if ip.To4() != nil {
		splitAddress := strings.Split(ip.String(), ".")

		for i, j := 0, len(splitAddress)-1; i < len(splitAddress)/2; i, j = i+1, j-1 {
			splitAddress[i], splitAddress[j] = splitAddress[j], splitAddress[i]
		}

		return strings.Join(splitAddress, ".")
	}
	return ""
}

func query(rbl string, host string, r *Result) {
	r.Listed = false

	lookup := fmt.Sprintf("%s.%s", host, rbl)

	res, err := net.LookupHost(lookup)
	if len(res) > 0 {
		r.Listed = true
		txt, _ := net.LookupTXT(lookup)
		if len(txt) > 0 {
			r.Text = txt[0]
		}
	}
	if err != nil {
		r.Error = true
		r.ErrorType = err
	}

	return
}

/*
Lookup performs the search and returns the RBLResults
*/
func Lookup(rblList string, targetHost string) (r RBLResults) {
	r.List = rblList
	r.Host = targetHost

	if ip, err := net.LookupIP(targetHost); err == nil {
		for _, addr := range ip {
			if addr.To4() != nil {
				res := Result{}
				res.Address = addr.String()

				addr := Reverse(addr)

				query(rblList, addr, &res)

				r.Results = append(r.Results, res)

			}
		}
	}
	return
}
<|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2015 Romain LÉTENDART
//
// See LICENSE file.
package main

import (
	"flag"
	"fmt"
	"github.com/romainletendart/goxxx/core"
	"github.com/romainletendart/goxxx/database"
	"github.com/romainletendart/goxxx/memo"
	"github.com/romainletendart/goxxx/search"
	"github.com/romainletendart/goxxx/webinfo"
	"log"
	"os"
)

func getOptions() (nick, server, channel, channelKey string, success bool) {
	flag.StringVar(&channel, "channel", "", "IRC channel name")
	flag.StringVar(&channelKey, "key", "", "IRC channel key (optional)")
	flag.StringVar(&nick, "nick", "goxxx", "the bot's nickname (optional)")
	flag.StringVar(&server, "server", "chat.freenode.net:6697", "IRC_SERVER[:PORT] (optional)")
	flag.Usage = func() {
		fmt.Println("Usage:", os.Args[0], "-channel CHANNEL [ARGUMENTS]")
		fmt.Println()
		fmt.Println("Arguments description:")
		flag.PrintDefaults()
	}
	flag.Parse()

	if channel == "" {
		flag.Usage()
		success = false
	} else {
		success = true
	}

	return
}

func main() {

	// Set log output to a file
	logFile, err := os.OpenFile("./logs.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		log.Fatalf("Error opening file: %v", err)
	}
	defer logFile.Close()
	log.SetOutput(logFile)

	nick, server, channel, channelKey, success := getOptions()
	if !success {
		log.Fatal("Initialisation failed (getOptions())")
		return
	}

	db := database.InitDatabase("", false)
	defer db.Close()

	bot := core.Bot{
		Nick:       nick,
		Server:     server,
		Channel:    channel,
		ChannelKey: channelKey,
	}
	bot.Init()
	memo.Init(db)
	webinfo.Init(db)
	search.Init()

	bot.AddMsgHandler(webinfo.HandleUrls, bot.ReplyToAll)
	bot.AddMsgHandler(memo.SendMemo, bot.ReplyToNick)

	bot.AddCmdHandler(memo.HandleMemoCmd, bot.ReplyToAll)
	bot.AddCmdHandler(memo.HandleMemoStatusCmd, bot.ReplyToNick)
	bot.AddCmdHandler(search.HandleSearchCmd, bot.ReplyToAll)

	bot.Run()
}
<commit_msg>Added version number<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2015 Romain LÉTENDART
//
// See LICENSE file.
package main

import (
	"flag"
	"fmt"
	"github.com/romainletendart/goxxx/core"
	"github.com/romainletendart/goxxx/database"
	"github.com/romainletendart/goxxx/memo"
	"github.com/romainletendart/goxxx/search"
	"github.com/romainletendart/goxxx/webinfo"
	"log"
	"os"
)

const (
	// Application version
	global_version string = "1.0.0"

	// Equivalent to enums (cf. https://golang.org/ref/spec#Iota)
	flags_exit    = iota //  == 0
	flags_success        //  == 1
	flags_failure        //  == 2
)

func getOptions() (nick, server, channel, channelKey string, returnCode int) {
	flag.StringVar(&channel, "channel", "", "IRC channel name")
	flag.StringVar(&channelKey, "key", "", "IRC channel key (optional)")
	flag.StringVar(&nick, "nick", "goxxx", "the bot's nickname (optional)")
	flag.StringVar(&server, "server", "chat.freenode.net:6697", "IRC_SERVER[:PORT] (optional)")
	version := flag.Bool("version", false, "Display goxxx version")

	flag.Usage = func() {
		fmt.Println("Usage:", os.Args[0], "-channel CHANNEL [ARGUMENTS]")
		fmt.Println()
		fmt.Println("Arguments description:")
		flag.PrintDefaults()
	}

	flag.Parse()

	if *version {
		fmt.Printf("\nGoxxx version: %s\n\n", global_version)
		returnCode = flags_exit
		return
	}

	if channel == "" {
		flag.Usage()
		returnCode = flags_failure
	} else {
		returnCode = flags_success
	}

	return
}

func main() {

	// Set log output to a file
	logFile, err := os.OpenFile("./logs.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		log.Fatalf("Error opening file: %v", err)
	}
	defer logFile.Close()
	log.SetOutput(logFile)

	nick, server, channel, channelKey, returnCode := getOptions()
	if returnCode == flags_exit {
		return
	} else if returnCode == flags_failure {
		log.Fatal("Initialisation failed (getOptions())")
	}

	db := database.InitDatabase("", false)
	defer db.Close()

	bot := core.Bot{
		Nick:       nick,
		Server:     server,
		Channel:    channel,
		ChannelKey: channelKey,
	}
	bot.Init()
	memo.Init(db)
	webinfo.Init(db)
	search.Init()

	bot.AddMsgHandler(webinfo.HandleUrls, bot.ReplyToAll)
	bot.AddMsgHandler(memo.SendMemo, bot.ReplyToNick)

	bot.AddCmdHandler(memo.HandleMemoCmd, bot.ReplyToAll)
	bot.AddCmdHandler(memo.HandleMemoStatusCmd, bot.ReplyToNick)
	bot.AddCmdHandler(search.HandleSearchCmd, bot.ReplyToAll)

	bot.Run()
}
<|endoftext|>


<commit_before>package main

import "fmt"

func main() {
  fmt.Println("Hello")
  fmt.Println("Hallo")
  fmt.Println("Hola")
  fmt.Println("End my suffering")
  fmt.Println("Bonjour")
}
<commit_msg>Fikser konflikt<commit_after>package main

import "fmt"

func main() {
  fmt.Println("Hello")
  fmt.Println("Hallo")
  fmt.Println("Hola")
  fmt.Println("End my suffering")
  fmt.Println("Bonjour")
  fmt.Println("Heisann")
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"net/http"

	"github.com/danmane/abalone/go/api"
	"github.com/danmane/abalone/go/game"
)

var (
	playAgainstHuman = flag.Bool("playAgainstHuman", false, "play against human on frontend rather than AI vs AI")
	humanPort        = flag.String("humanPort", "1337", "port for javascript frontend")
	aiPort1          = flag.String("aiPort1", "3423", "port for first ai")
	aiPort2          = flag.String("aiPort2", "3424", "port for second ai (if present)")
)

func main() {
	flag.Parse()
	if err := run(); err != nil {
		log.Fatal(err)
	}
}

func run() error {
	whiteAI := api.Player{}
	blackAI := api.Player{}
	whiteAgent := PlayerInstance{Player: whiteAI, Port: *aiPort1}
	blackAgent := PlayerInstance{Player: blackAI, Port: *aiPort2}
	start := game.Standard
	result := playAIGame(whiteAgent, blackAgent, start)
	fmt.Println(result)
	return nil
}

type PlayerInstance struct {
	Player api.Player
	Port   string
}

func gameFromAI(state *game.State, port string) (*game.State, error) {
	var buf bytes.Buffer
	if err := json.NewEncoder(&buf).Encode(state); err != nil {
		return nil, err
	}
	resp, err := http.Post("http://localhost:"+port+"/move", "application/json", &buf)
	if err != nil {
		return nil, err
	}
	responseGame := &game.State{}
	if err := json.NewDecoder(resp.Body).Decode(responseGame); err != nil {
		return nil, err
	}
	resp.Body.Close()
	if !state.ValidFuture(responseGame) {
		return fmt.Errorf("game parsed correctly, but isn't a valid future"), nil
	}
	return responseGame, nil
}

func playAIGame(whiteAgent, blackAgent PlayerInstance, startState game.State) api.GameResult {
	states := []game.State{startState}
	currentGame := &startState
	victory := api.NoVictory
	outcome := game.NullOutcome
	for !currentGame.GameOver() {
		var nextAI PlayerInstance
		if currentGame.NextPlayer == game.White {
			nextAI = whiteAgent
		} else {
			nextAI = blackAgent
		}
		futureGame, err := gameFromAI(nextAI.Port, currentGame)
		if err != nil {
			fmt.Println(err)
			victory = api.InvalidResponse
			outcome = currentGame.NextPlayer.Loses()
			return api.GameResult{
				White:         whiteAgent.Player,
				Black:         blackAgent.Player,
				Outcome:       outcome,
				VictoryReason: victory,
				States:        states,
			}
		}
		currentGame = futureGame
		states = append(states, *currentGame)
	}

	outcome = currentGame.Winner()
	if currentGame.MovesRemaining == 0 {
		// TODO win on last move = stones depleted
		victory = api.MovesDepleted
		fmt.Println("someone won by move depletion")
	} else {
		victory = api.StonesDepleted
		fmt.Println("someone won by stone depletion")
	}
	return api.GameResult{
		White:         whiteAgent.Player,
		Black:         blackAgent.Player,
		Outcome:       outcome,
		VictoryReason: victory,
		States:        states,
	}

}
<commit_msg>fix(game operator) compilation error<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"net/http"

	"github.com/danmane/abalone/go/api"
	"github.com/danmane/abalone/go/game"
)

var (
	playAgainstHuman = flag.Bool("playAgainstHuman", false, "play against human on frontend rather than AI vs AI")
	humanPort        = flag.String("humanPort", "1337", "port for javascript frontend")
	aiPort1          = flag.String("aiPort1", "3423", "port for first ai")
	aiPort2          = flag.String("aiPort2", "3424", "port for second ai (if present)")
)

func main() {
	flag.Parse()
	if err := run(); err != nil {
		log.Fatal(err)
	}
}

func run() error {
	whiteAI := api.Player{}
	blackAI := api.Player{}
	whiteAgent := PlayerInstance{Player: whiteAI, Port: *aiPort1}
	blackAgent := PlayerInstance{Player: blackAI, Port: *aiPort2}
	start := game.Standard
	result := playAIGame(whiteAgent, blackAgent, start)
	fmt.Println(result)
	return nil
}

type PlayerInstance struct {
	Player api.Player
	Port   string
}

func gameFromAI(state *game.State, port string) (*game.State, error) {
	var buf bytes.Buffer
	if err := json.NewEncoder(&buf).Encode(state); err != nil {
		return nil, err
	}
	resp, err := http.Post("http://localhost:"+port+"/move", "application/json", &buf)
	if err != nil {
		return nil, err
	}
	responseGame := &game.State{}
	if err := json.NewDecoder(resp.Body).Decode(responseGame); err != nil {
		return nil, err
	}
	resp.Body.Close()
	if !state.ValidFuture(responseGame) {
		return nil, fmt.Errorf("game parsed correctly, but isn't a valid future")
	}
	return responseGame, nil
}

func playAIGame(whiteAgent, blackAgent PlayerInstance, startState game.State) api.GameResult {
	states := []game.State{startState}
	currentGame := &startState
	victory := api.NoVictory
	outcome := game.NullOutcome
	for !currentGame.GameOver() {
		var nextAI PlayerInstance
		if currentGame.NextPlayer == game.White {
			nextAI = whiteAgent
		} else {
			nextAI = blackAgent
		}
		futureGame, err := gameFromAI(currentGame, nextAI.Port)
		if err != nil {
			fmt.Println(err)
			victory = api.InvalidResponse
			outcome = currentGame.NextPlayer.Loses()
			return api.GameResult{
				White:         whiteAgent.Player,
				Black:         blackAgent.Player,
				Outcome:       outcome,
				VictoryReason: victory,
				States:        states,
			}
		}
		currentGame = futureGame
		states = append(states, *currentGame)
	}

	outcome = currentGame.Winner()
	if currentGame.MovesRemaining == 0 {
		// TODO win on last move = stones depleted
		victory = api.MovesDepleted
		fmt.Println("someone won by move depletion")
	} else {
		victory = api.StonesDepleted
		fmt.Println("someone won by stone depletion")
	}
	return api.GameResult{
		White:         whiteAgent.Player,
		Black:         blackAgent.Player,
		Outcome:       outcome,
		VictoryReason: victory,
		States:        states,
	}

}
<|endoftext|>