<commit_before>package astrolabe

import (
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"

	"github.com/go-martini/martini"
)

// This function acts as a setup for other tests.
func setup() *httptest.ResponseRecorder {
	m := martini.Classic()
	m.Use(ExposeEndpoint(m.Router))

	res := httptest.NewRecorder()
	req, _ := http.NewRequest("GET", "/martini/routes", nil)

	m.ServeHTTP(res, req)

	return res
}

// This function is used as a setup but with a route defined.
func setupWithRoute(method string, handler martini.Handler) *httptest.ResponseRecorder {
	m := martini.Classic()

	switch method {
	case "GET":
		m.Get("/posts", handler)
	case "POST":
		m.Post("/posts", handler)
	case "PUT":
		m.Put("/posts/:id", handler)
	case "PATCH":
		m.Patch("/posts/:id", handler)
	case "OPTIONS":
		m.Options("/posts", handler)
	case "HEAD":
		m.Head("/posts", handler)
	case "DELETE":
		m.Delete("/posts/:id", handler)
	}

	m.Use(ExposeEndpoint(m.Router))

	res := httptest.NewRecorder()
	req, _ := http.NewRequest("GET", "/martini/routes", nil)

	m.ServeHTTP(res, req)

	return res
}

// Test that /martini/routes endpoint is accessible and the content-type is set to text/html.
func TestExposeEndpoint(t *testing.T) {
	res := setup()

	if res.Code != 200 {
		t.Error("Response is not 200.")
	}

	if res.HeaderMap.Get("Content-Type") != "text/html" {
		t.Error("Expecting the Content-Type to be text/html.")
	}
}

// This checks the endpoint is not exposed when the MARTINI.ENV is anything other than development.
func TestNotExposedIfNotInDevelopment(t *testing.T) {
	res := setup()

	// Check that we are not in development.
	if martini.Env != martini.Dev {
		if res.Code != http.StatusNotFound {
			t.Error("/martini/routes endpoint should not be exposed when environment is not development.")
		}
	}
}

// Test GET routes are displayed.
func TestGetRoute(t *testing.T) {
	res := setupWithRoute("GET", func(w http.ResponseWriter, r *http.Request) string {
		return "a GET route"
	})

	if !strings.Contains(res.Body.String(), "GET") {
		t.Error("The GET route should be displayed.")
	}

	if !strings.Contains(res.Body.String(), "/posts") {
		t.Error("The route path should be displayed.")
	}
}

// Test POST routes are displayed.
func TestPostRoute(t *testing.T) {
	res := setupWithRoute("POST", func(w http.ResponseWriter, r *http.Request) string {
		return "a POST route"
	})

	if !strings.Contains(res.Body.String(), "POST") {
		t.Error("The POST route should be displayed.")
	}

	if !strings.Contains(res.Body.String(), "/posts") {
		t.Error("The route path should be displayed.")
	}
}

// Test PUT routes are displayed.
func TestPutRoute(t *testing.T) {
	res := setupWithRoute("PUT", func(w http.ResponseWriter, r *http.Request) string {
		return "a PUT route"
	})

	if !strings.Contains(res.Body.String(), "PUT") {
		t.Error("The PUT route should be displayed.")
	}

	if !strings.Contains(res.Body.String(), "/posts/:id") {
		t.Error("The route path should be displayed.")
	}
}

// Test PATCH routes are displayed.
func TestPatchRoute(t *testing.T) {
	res := setupWithRoute("PATCH", func(w http.ResponseWriter, r *http.Request) string {
		return "a PATCH route"
	})

	if !strings.Contains(res.Body.String(), "PATCH") {
		t.Error("The PATCH route should be displayed.")
	}

	if !strings.Contains(res.Body.String(), "/posts/:id") {
		t.Error("The route path should be displayed.")
	}
}

// Test OPTIONS routes are displayed.
func TestOptionsRoute(t *testing.T) {
	res := setupWithRoute("OPTIONS", func(w http.ResponseWriter, r *http.Request) string {
		return "an OPTIONS route"
	})

	if !strings.Contains(res.Body.String(), "OPTIONS") {
		t.Error("The OPTIONS route should be displayed.")
	}

	if !strings.Contains(res.Body.String(), "/posts") {
		t.Error("The route path should be displayed.")
	}
}

// Test HEAD routes are displayed.
func TestHeadRoute(t *testing.T) {
	res := setupWithRoute("HEAD", func(w http.ResponseWriter, r *http.Request) string {
		return "a HEAD route"
	})

	if !strings.Contains(res.Body.String(), "HEAD") {
		t.Error("The HEAD route should be displayed.")
	}

	if !strings.Contains(res.Body.String(), "/posts") {
		t.Error("The route path should be displayed.")
	}
}

// Test DELETE routes are displayed.
func TestDeleteRoute(t *testing.T) {
	res := setupWithRoute("DELETE", func(w http.ResponseWriter, r *http.Request) string {
		return "a DELETE route"
	})

	if !strings.Contains(res.Body.String(), "DELETE") {
		t.Error("The DELETE route should be displayed.")
	}

	if !strings.Contains(res.Body.String(), "/posts") {
		t.Error("The route path should be displayed.")
	}
}
<commit_msg>Test that /martini/routes endpoint is not displayed among routes<commit_after>package astrolabe

import (
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"

	"github.com/go-martini/martini"
)

// This function acts as a setup for other tests.
func setup() *httptest.ResponseRecorder {
	m := martini.Classic()
	m.Use(ExposeEndpoint(m.Router))

	res := httptest.NewRecorder()
	req, _ := http.NewRequest("GET", "/martini/routes", nil)

	m.ServeHTTP(res, req)

	return res
}

// This function is used as a setup but with a route defined.
func setupWithRoute(method string, handler martini.Handler) *httptest.ResponseRecorder {
	m := martini.Classic()

	switch method {
	case "GET":
		m.Get("/posts", handler)
	case "POST":
		m.Post("/posts", handler)
	case "PUT":
		m.Put("/posts/:id", handler)
	case "PATCH":
		m.Patch("/posts/:id", handler)
	case "OPTIONS":
		m.Options("/posts", handler)
	case "HEAD":
		m.Head("/posts", handler)
	case "DELETE":
		m.Delete("/posts/:id", handler)
	}

	m.Use(ExposeEndpoint(m.Router))

	res := httptest.NewRecorder()
	req, _ := http.NewRequest("GET", "/martini/routes", nil)

	m.ServeHTTP(res, req)

	return res
}

// Test that /martini/routes endpoint is accessible and the content-type is set to text/html.
func TestExposeEndpoint(t *testing.T) {
	res := setup()

	if res.Code != 200 {
		t.Error("Response is not 200.")
	}

	if res.HeaderMap.Get("Content-Type") != "text/html" {
		t.Error("Expecting the Content-Type to be text/html.")
	}
}

// This checks the endpoint is not exposed when the MARTINI.ENV is anything other than development.
func TestNotExposedIfNotInDevelopment(t *testing.T) {
	res := setup()

	// Check that we are not in development.
	if martini.Env != martini.Dev {
		if res.Code != http.StatusNotFound {
			t.Error("/martini/routes endpoint should not be exposed when environment is not development.")
		}
	}
}

// This will test that /martini/routes endpoint is not displayed in the page.
func TestEndpointNotInRoutes(t *testing.T) {
	res := setup()

	if strings.Contains(res.Body.String(), "/martini/routes") {
		t.Error("/martini/routes endpoint should not be displayed among other routes.")
	}
}

// Test GET routes are displayed.
func TestGetRoute(t *testing.T) {
	res := setupWithRoute("GET", func(w http.ResponseWriter, r *http.Request) string {
		return "a GET route"
	})

	if !strings.Contains(res.Body.String(), "GET") {
		t.Error("The GET route should be displayed.")
	}

	if !strings.Contains(res.Body.String(), "/posts") {
		t.Error("The route path should be displayed.")
	}
}

// Test POST routes are displayed.
func TestPostRoute(t *testing.T) {
	res := setupWithRoute("POST", func(w http.ResponseWriter, r *http.Request) string {
		return "a POST route"
	})

	if !strings.Contains(res.Body.String(), "POST") {
		t.Error("The POST route should be displayed.")
	}

	if !strings.Contains(res.Body.String(), "/posts") {
		t.Error("The route path should be displayed.")
	}
}

// Test PUT routes are displayed.
func TestPutRoute(t *testing.T) {
	res := setupWithRoute("PUT", func(w http.ResponseWriter, r *http.Request) string {
		return "a PUT route"
	})

	if !strings.Contains(res.Body.String(), "PUT") {
		t.Error("The PUT route should be displayed.")
	}

	if !strings.Contains(res.Body.String(), "/posts/:id") {
		t.Error("The route path should be displayed.")
	}
}

// Test PATCH routes are displayed.
func TestPatchRoute(t *testing.T) {
	res := setupWithRoute("PATCH", func(w http.ResponseWriter, r *http.Request) string {
		return "a PATCH route"
	})

	if !strings.Contains(res.Body.String(), "PATCH") {
		t.Error("The PATCH route should be displayed.")
	}

	if !strings.Contains(res.Body.String(), "/posts/:id") {
		t.Error("The route path should be displayed.")
	}
}

// Test OPTIONS routes are displayed.
func TestOptionsRoute(t *testing.T) {
	res := setupWithRoute("OPTIONS", func(w http.ResponseWriter, r *http.Request) string {
		return "an OPTIONS route"
	})

	if !strings.Contains(res.Body.String(), "OPTIONS") {
		t.Error("The OPTIONS route should be displayed.")
	}

	if !strings.Contains(res.Body.String(), "/posts") {
		t.Error("The route path should be displayed.")
	}
}

// Test HEAD routes are displayed.
func TestHeadRoute(t *testing.T) {
	res := setupWithRoute("HEAD", func(w http.ResponseWriter, r *http.Request) string {
		return "a HEAD route"
	})

	if !strings.Contains(res.Body.String(), "HEAD") {
		t.Error("The HEAD route should be displayed.")
	}

	if !strings.Contains(res.Body.String(), "/posts") {
		t.Error("The route path should be displayed.")
	}
}

// Test DELETE routes are displayed.
func TestDeleteRoute(t *testing.T) {
	res := setupWithRoute("DELETE", func(w http.ResponseWriter, r *http.Request) string {
		return "a DELETE route"
	})

	if !strings.Contains(res.Body.String(), "DELETE") {
		t.Error("The DELETE route should be displayed.")
	}

	if !strings.Contains(res.Body.String(), "/posts") {
		t.Error("The route path should be displayed.")
	}
}
<|endoftext|>


<commit_before>package utils

import (
	"errors"
	"io"
	"log"
	"net/http"
	"os"
	"reflect"
	"strings"
	"text/template"
	"unicode"

	"github.com/hacdias/caddy-hugo/assets"
	"github.com/hacdias/caddy-hugo/config"
	"github.com/spf13/hugo/commands"
)

// CanBeEdited checks if the extension of a file is supported by the editor
func CanBeEdited(filename string) bool {
	extensions := [...]string{
		"md", "markdown", "mdown", "mmark",
		"asciidoc", "adoc", "ad",
		"rst",
		".json", ".toml", ".yaml",
		".css", ".sass", ".scss",
		".js",
		".html",
		".txt",
	}

	for _, extension := range extensions {
		if strings.HasSuffix(filename, extension) {
			return true
		}
	}

	return false
}

// CopyFile is used to copy a file
func CopyFile(old, new string) error {
	// Open the file and create a new one
	r, err := os.Open(old)
	if err != nil {
		return err
	}
	defer r.Close()

	w, err := os.Create(new)
	if err != nil {
		return err
	}
	defer w.Close()

	// Copy the content
	_, err = io.Copy(w, r)
	if err != nil {
		return err
	}

	return nil
}

// Defined checks if variable is defined in a struct
func Defined(data interface{}, field string) bool {
	t := reflect.Indirect(reflect.ValueOf(data)).Type()

	if t.Kind() != reflect.Struct {
		log.Print("Non-struct type not allowed.")
		return false
	}

	_, b := t.FieldByName(field)
	return b
}

// Dict allows to send more than one variable into a template
func Dict(values ...interface{}) (map[string]interface{}, error) {
	if len(values)%2 != 0 {
		return nil, errors.New("invalid dict call")
	}
	dict := make(map[string]interface{}, len(values)/2)
	for i := 0; i < len(values); i += 2 {
		key, ok := values[i].(string)
		if !ok {
			return nil, errors.New("dict keys must be strings")
		}
		dict[key] = values[i+1]
	}

	return dict, nil
}

// GetTemplate is used to get a ready to use template based on the url and on
// other sent templates
func GetTemplate(r *http.Request, functions template.FuncMap, templates ...string) (*template.Template, error) {
	// If this is a pjax request, use the minimal template to send only
	// the main content
	if r.Header.Get("X-PJAX") == "true" {
		templates = append(templates, "base_minimal")
	} else {
		templates = append(templates, "base_full")
	}

	var tpl *template.Template

	// For each template, add it to the the tpl variable
	for i, t := range templates {
		// Get the template from the assets
		page, err := assets.Asset("templates/" + t + ".tmpl")

		// Check if there is some error. If so, the template doesn't exist
		if err != nil {
			log.Print(err)
			return new(template.Template), err
		}

		// If it's the first iteration, creates a new template and add the
		// functions map
		if i == 0 {
			tpl, err = template.New(t).Funcs(functions).Parse(string(page))
		} else {
			tpl, err = tpl.Parse(string(page))
		}

		if err != nil {
			log.Print(err)
			return new(template.Template), err
		}
	}

	return tpl, nil
}

// IsMap checks if some variable is a map
func IsMap(sth interface{}) bool {
	return reflect.ValueOf(sth).Kind() == reflect.Map
}

// IsSlice checks if some variable is a slice
func IsSlice(sth interface{}) bool {
	return reflect.ValueOf(sth).Kind() == reflect.Slice
}

// ParseComponents parses the components of an URL creating an array
func ParseComponents(r *http.Request) []string {
	//The URL that the user queried.
	path := r.URL.Path
	path = strings.TrimSpace(path)
	//Cut off the leading and trailing forward slashes, if they exist.
	//This cuts off the leading forward slash.
	if strings.HasPrefix(path, "/") {
		path = path[1:]
	}
	//This cuts off the trailing forward slash.
	if strings.HasSuffix(path, "/") {
		cutOffLastCharLen := len(path) - 1
		path = path[:cutOffLastCharLen]
	}
	//We need to isolate the individual components of the path.
	components := strings.Split(path, "/")
	return components
}

// Run is used to run the static website generator
func Run(c *config.Config) {
	os.RemoveAll(c.Path + "public")

	commands.MainSite = nil
	c.Args = append([]string{"--source", c.Path}, c.Args...)
	commands.HugoCmd.ParseFlags(c.Args)
	if err := commands.HugoCmd.RunE(nil, nil); err != nil {
		log.Print(err)
	}
}

var splitCapitalizeExceptions = map[string]string{
	"youtube":    "YouTube",
	"github":     "GitHub",
	"googleplus": "Google Plus",
	"linkedin":   "LinkedIn",
}

// SplitCapitalize splits a string by its uppercase letters and capitalize the
// first letter of the string
func SplitCapitalize(name string) string {
	if val, ok := splitCapitalizeExceptions[strings.ToLower(name)]; ok {
		return val
	}

	var words []string
	l := 0
	for s := name; s != ""; s = s[l:] {
		l = strings.IndexFunc(s[1:], unicode.IsUpper) + 1
		if l <= 0 {
			l = len(s)
		}
		words = append(words, s[:l])
	}

	name = ""

	for _, element := range words {
		name += element + " "
	}

	name = strings.ToLower(name[:len(name)-1])
	name = strings.ToUpper(string(name[0])) + name[1:]

	return name
}
<commit_msg>add viper.reset<commit_after>package utils

import (
	"errors"
	"io"
	"log"
	"net/http"
	"os"
	"reflect"
	"strings"
	"text/template"
	"unicode"

	"github.com/hacdias/caddy-hugo/assets"
	"github.com/hacdias/caddy-hugo/config"
	"github.com/spf13/hugo/commands"
	"github.com/spf13/viper"
)

// CanBeEdited checks if the extension of a file is supported by the editor
func CanBeEdited(filename string) bool {
	extensions := [...]string{
		"md", "markdown", "mdown", "mmark",
		"asciidoc", "adoc", "ad",
		"rst",
		".json", ".toml", ".yaml",
		".css", ".sass", ".scss",
		".js",
		".html",
		".txt",
	}

	for _, extension := range extensions {
		if strings.HasSuffix(filename, extension) {
			return true
		}
	}

	return false
}

// CopyFile is used to copy a file
func CopyFile(old, new string) error {
	// Open the file and create a new one
	r, err := os.Open(old)
	if err != nil {
		return err
	}
	defer r.Close()

	w, err := os.Create(new)
	if err != nil {
		return err
	}
	defer w.Close()

	// Copy the content
	_, err = io.Copy(w, r)
	if err != nil {
		return err
	}

	return nil
}

// Defined checks if variable is defined in a struct
func Defined(data interface{}, field string) bool {
	t := reflect.Indirect(reflect.ValueOf(data)).Type()

	if t.Kind() != reflect.Struct {
		log.Print("Non-struct type not allowed.")
		return false
	}

	_, b := t.FieldByName(field)
	return b
}

// Dict allows to send more than one variable into a template
func Dict(values ...interface{}) (map[string]interface{}, error) {
	if len(values)%2 != 0 {
		return nil, errors.New("invalid dict call")
	}
	dict := make(map[string]interface{}, len(values)/2)
	for i := 0; i < len(values); i += 2 {
		key, ok := values[i].(string)
		if !ok {
			return nil, errors.New("dict keys must be strings")
		}
		dict[key] = values[i+1]
	}

	return dict, nil
}

// GetTemplate is used to get a ready to use template based on the url and on
// other sent templates
func GetTemplate(r *http.Request, functions template.FuncMap, templates ...string) (*template.Template, error) {
	// If this is a pjax request, use the minimal template to send only
	// the main content
	if r.Header.Get("X-PJAX") == "true" {
		templates = append(templates, "base_minimal")
	} else {
		templates = append(templates, "base_full")
	}

	var tpl *template.Template

	// For each template, add it to the the tpl variable
	for i, t := range templates {
		// Get the template from the assets
		page, err := assets.Asset("templates/" + t + ".tmpl")

		// Check if there is some error. If so, the template doesn't exist
		if err != nil {
			log.Print(err)
			return new(template.Template), err
		}

		// If it's the first iteration, creates a new template and add the
		// functions map
		if i == 0 {
			tpl, err = template.New(t).Funcs(functions).Parse(string(page))
		} else {
			tpl, err = tpl.Parse(string(page))
		}

		if err != nil {
			log.Print(err)
			return new(template.Template), err
		}
	}

	return tpl, nil
}

// IsMap checks if some variable is a map
func IsMap(sth interface{}) bool {
	return reflect.ValueOf(sth).Kind() == reflect.Map
}

// IsSlice checks if some variable is a slice
func IsSlice(sth interface{}) bool {
	return reflect.ValueOf(sth).Kind() == reflect.Slice
}

// ParseComponents parses the components of an URL creating an array
func ParseComponents(r *http.Request) []string {
	//The URL that the user queried.
	path := r.URL.Path
	path = strings.TrimSpace(path)
	//Cut off the leading and trailing forward slashes, if they exist.
	//This cuts off the leading forward slash.
	if strings.HasPrefix(path, "/") {
		path = path[1:]
	}
	//This cuts off the trailing forward slash.
	if strings.HasSuffix(path, "/") {
		cutOffLastCharLen := len(path) - 1
		path = path[:cutOffLastCharLen]
	}
	//We need to isolate the individual components of the path.
	components := strings.Split(path, "/")
	return components
}

// Run is used to run the static website generator
func Run(c *config.Config) {
	os.RemoveAll(c.Path + "public")

	commands.MainSite = nil
	viper.Reset()
	c.Args = append([]string{"--source", c.Path}, c.Args...)
	commands.HugoCmd.ParseFlags(c.Args)
	if err := commands.HugoCmd.RunE(nil, nil); err != nil {
		log.Print(err)
	}
}

var splitCapitalizeExceptions = map[string]string{
	"youtube":    "YouTube",
	"github":     "GitHub",
	"googleplus": "Google Plus",
	"linkedin":   "LinkedIn",
}

// SplitCapitalize splits a string by its uppercase letters and capitalize the
// first letter of the string
func SplitCapitalize(name string) string {
	if val, ok := splitCapitalizeExceptions[strings.ToLower(name)]; ok {
		return val
	}

	var words []string
	l := 0
	for s := name; s != ""; s = s[l:] {
		l = strings.IndexFunc(s[1:], unicode.IsUpper) + 1
		if l <= 0 {
			l = len(s)
		}
		words = append(words, s[:l])
	}

	name = ""

	for _, element := range words {
		name += element + " "
	}

	name = strings.ToLower(name[:len(name)-1])
	name = strings.ToUpper(string(name[0])) + name[1:]

	return name
}
<|endoftext|>


<commit_before>package colonycore

import (
	"github.com/eaciit/dbox"
	"github.com/eaciit/orm/v1"
	"github.com/eaciit/toolkit"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

type Widget struct {
	orm.ModelBase
	ID           string     `json:"_id"`
	Title        string     `json:"title"`
	DataSourceId []string   `json:"dataSourceId"`
	Description  string     `json:"description"`
	Config       toolkit.Ms `json:"config"`
	Params       toolkit.M  `json:"params"`
	URL          string     `json:"url"`
}

type DataSourceWidget struct {
	ID   string      `json:"_id"`
	Data []toolkit.M `json:"data"`
}

func (w *Widget) TableName() string {
	return "widgets"
}

func (w *Widget) RecordID() interface{} {
	return w.ID
}

func (w *Widget) Get(search string) ([]Widget, error) {
	var query *dbox.Filter

	if search != "" {
		query = dbox.Contains("_id", search)
	}

	data := []Widget{}
	cursor, err := Find(new(Widget), query)
	if err != nil {
		return nil, err
	}
	if err := cursor.Fetch(&data, 0, false); err != nil {
		return nil, err
	}
	defer cursor.Close()
	return data, nil
}

func (w *Widget) GetById() error {
	if err := Get(w, w.ID); err != nil {
		return err
	}
	return nil
}

func (w *Widget) Save() error {
	if err := Save(w); err != nil {
		return err
	}
	return nil
}

func GetPath(root string) (string, error) {
	absRoot, err := filepath.Abs(root)
	if err != nil {
		return "", err
	}
	var _path string
	var indexPath []string
	var configPath []string
	var assetPath []string
	walkFunc := func(path string, info os.FileInfo, err error) error {
		_path, filename := filepath.Split(path)
		if strings.Compare(filename, "index.html") == 0 {
			indexPath = append(indexPath, _path)
		}
		if strings.Compare(filename, "config.json") == 0 {
			configPath = append(configPath, _path)
		}

		if strings.Compare(filename, "assets") == 0 {
			assetPath = append(assetPath, _path)
		}
		return nil
	}
	if err = filepath.Walk(absRoot, walkFunc); err != nil {
		return "", err
	}

	for _, valIndex := range indexPath {
		for _, valConfig := range configPath {
			for _, valAsset := range assetPath {
				if valIndex == valConfig && valConfig == valAsset {
					_path = valConfig
					break
				}
			}

		}
	}
	return _path, nil
}

func (w *Widget) ExtractFile(compressedSource string, fileName string) (toolkit.Ms, error) {
	compressedFile := filepath.Join(compressedSource, fileName)
	extractDest := filepath.Join(compressedSource, w.ID)

	if err := os.RemoveAll(extractDest); err != nil {
		return nil, err
	}

	if strings.Contains(fileName, ".tar.gz") {
		if err := toolkit.TarGzExtract(compressedFile, extractDest); err != nil {
			return nil, err
		}
	} else if strings.Contains(fileName, ".gz") {
		if err := toolkit.GzExtract(compressedFile, extractDest); err != nil {
			return nil, err
		}
	} else if strings.Contains(fileName, ".tar") {
		if err := toolkit.TarExtract(compressedFile, extractDest); err != nil {
			return nil, err
		}
	} else if strings.Contains(fileName, ".zip") {
		if err := toolkit.ZipExtract(compressedFile, extractDest); err != nil {
			return nil, err
		}
	}

	if err := os.Remove(compressedFile); err != nil {
		return nil, err
	}

	path, err := GetPath(extractDest)
	if err != nil {
		return nil, err
	}

	urlPath := filepath.ToSlash(path)
	splitPath := strings.SplitAfter(urlPath, "/data-root/widget/")
	w.URL = strings.Join([]string{w.URL, "res-widget", splitPath[1]}, "/")

	getConfigFile := filepath.Join(path, "config.json")
	content, err := ioutil.ReadFile(getConfigFile)
	if err != nil {
		return nil, err
	}

	result := toolkit.Ms{}
	err = toolkit.Unjson(content, &result)
	if err != nil {
		return nil, err
	}

	return result, nil
}

func (w *Widget) Delete(compressedSource string) error {
	extractDest := filepath.Join(compressedSource, w.ID)
	if err := Delete(w); err != nil {
		return err
	}

	if err := os.RemoveAll(extractDest); err != nil {
		return err
	}
	return nil
}
<commit_msg>bug fix on widget model<commit_after>package colonycore

import (
	"errors"
	"github.com/eaciit/dbox"
	"github.com/eaciit/orm/v1"
	"github.com/eaciit/toolkit"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

type Widget struct {
	orm.ModelBase
	ID           string     `json:"_id"`
	Title        string     `json:"title"`
	DataSourceId []string   `json:"dataSourceId"`
	Description  string     `json:"description"`
	Config       toolkit.Ms `json:"config"`
	Params       toolkit.M  `json:"params"`
	URL          string     `json:"url"`
}

type DataSourceWidget struct {
	ID   string      `json:"_id"`
	Data []toolkit.M `json:"data"`
}

func (w *Widget) TableName() string {
	return "widgets"
}

func (w *Widget) RecordID() interface{} {
	return w.ID
}

func (w *Widget) Get(search string) ([]Widget, error) {
	var query *dbox.Filter

	if search != "" {
		query = dbox.Contains("_id", search)
	}

	data := []Widget{}
	cursor, err := Find(new(Widget), query)
	if err != nil {
		return nil, err
	}
	if err := cursor.Fetch(&data, 0, false); err != nil {
		return nil, err
	}
	defer cursor.Close()
	return data, nil
}

func (w *Widget) GetById() error {
	if err := Get(w, w.ID); err != nil {
		return err
	}
	return nil
}

func (w *Widget) Save() error {
	if err := Save(w); err != nil {
		return err
	}
	return nil
}

func GetPath(root string) (string, error) {
	absRoot, err := filepath.Abs(root)
	if err != nil {
		return "", err
	}
	var _path string
	var indexPath []string
	var configPath []string
	var assetPath []string
	walkFunc := func(path string, info os.FileInfo, err error) error {
		_path, filename := filepath.Split(path)
		if strings.Compare(filename, "index.html") == 0 {
			indexPath = append(indexPath, _path)
		}
		if strings.Compare(filename, "config.json") == 0 {
			configPath = append(configPath, _path)
		}

		if strings.Compare(filename, "assets") == 0 {
			assetPath = append(assetPath, _path)
		}
		return nil
	}
	if err = filepath.Walk(absRoot, walkFunc); err != nil {
		return "", err
	}

	for _, valIndex := range indexPath {
		for _, valConfig := range configPath {
			for _, valAsset := range assetPath {
				if valIndex == valConfig && valConfig == valAsset {
					_path = valConfig
					break
				}
			}

		}
	}
	return _path, nil
}

func (w *Widget) ExtractFile(compressedSource string, fileName string) (toolkit.Ms, error) {
	compressedFile := filepath.Join(compressedSource, fileName)
	extractDest := filepath.Join(compressedSource, w.ID)

	if err := os.RemoveAll(extractDest); err != nil {
		return nil, err
	}

	if strings.Contains(fileName, ".tar.gz") {
		if err := toolkit.TarGzExtract(compressedFile, extractDest); err != nil {
			return nil, err
		}
	} else if strings.Contains(fileName, ".gz") {
		if err := toolkit.GzExtract(compressedFile, extractDest); err != nil {
			return nil, err
		}
	} else if strings.Contains(fileName, ".tar") {
		if err := toolkit.TarExtract(compressedFile, extractDest); err != nil {
			return nil, err
		}
	} else if strings.Contains(fileName, ".zip") {
		if err := toolkit.ZipExtract(compressedFile, extractDest); err != nil {
			return nil, err
		}
	}

	if err := os.Remove(compressedFile); err != nil {
		return nil, err
	}

	path, err := GetPath(extractDest)
	if path == "" {
		return nil, errors.New("directory doesn't contains index.html")
	}
	if err != nil {
		return nil, err
	}

	urlPath := filepath.ToSlash(path)
	splitPath := strings.SplitAfter(urlPath, "/data-root/widget/")
	w.URL = strings.Join([]string{w.URL, "res-widget", splitPath[1]}, "/")

	getConfigFile := filepath.Join(path, "config.json")
	content, err := ioutil.ReadFile(getConfigFile)
	if err != nil {
		return nil, err
	}

	result := toolkit.Ms{}
	err = toolkit.Unjson(content, &result)
	if err != nil {
		return nil, err
	}

	return result, nil
}

func (w *Widget) Delete(compressedSource string) error {
	extractDest := filepath.Join(compressedSource, w.ID)
	if err := Delete(w); err != nil {
		return err
	}

	if err := os.RemoveAll(extractDest); err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>package rel

type AttributeNode struct {
	Name     SqlLiteralNode
	Relation Visitable
	BaseVisitable
}

func NewAttributeNode(v Visitable, name string) AttributeNode {
	return AttributeNode{
		Name:     Sql(name),
		Relation: v,
	}
}

func (node AttributeNode) Eq(v Visitable) EqualityNode {
	return NewEqualityNode(node, v)
}

func (node AttributeNode) Lt(v Visitable) LessThanNode {
	return LessThanNode{Left: node, Right: v}
}

func (node AttributeNode) LtEq(v Visitable) *LessThanOrEqualNode {
	return &LessThanOrEqualNode{Left: node, Right: v}
}

func (node AttributeNode) Gt(v Visitable) GreaterThanNode {
	return GreaterThanNode{Left: node, Right: v}
}

func (node AttributeNode) GtEqAny(visitable ...Visitable) *GroupingNode {
	var nodes []*NotEqualNode
	grouping := new(GroupingNode)
	for _, v := range visitable {
		nodes = append(nodes, node.Gt(v))
	}
	if len(nodes) > 0 {
		// unshift first node
		m, nodes := nodes[0], nodes[1:]
		var memo Visitable = m
		for _, n := range nodes {
			memo = &OrNode{Left: memo, Right: n}
		}
		grouping.Expr = append(grouping.Expr, memo)
	}
	return grouping
}

func (node AttributeNode) GtEq(v Visitable) *GreaterThanOrEqualNode {
	return &GreaterThanOrEqualNode{Left: node, Right: v}
}

func (node AttributeNode) Desc() DescendingNode {
	return DescendingNode{Expr: node}
}

func (node AttributeNode) Asc() AscendingNode {
	return AscendingNode{Expr: node}
}

func (node AttributeNode) Count() CountNode {
	return CountNode{Expressions: node}
}

func (node AttributeNode) As(v Visitable) AsNode {
	return AsNode{
		Left:  node,
		Right: v,
	}
}

func (node AttributeNode) In(v Visitable) Visitable {
	var ret Visitable
	switch val := v.(type) {
	case SelectManager:
		ret = &InNode{Left: node, Right: val.Ast}
	default:
		ret = &InNode{Left: node, Right: v}
	}
	return ret
}

func (node AttributeNode) NotEq(v Visitable) *NotEqualNode {
	return &NotEqualNode{
		Left:  node,
		Right: v,
	}
}

func (node AttributeNode) NotEqual(v Visitable) *NotEqualNode {
	return node.NotEq(v)
}

func (node AttributeNode) NotEqAny(visitable ...Visitable) *GroupingNode {
	var nodes []*NotEqualNode
	grouping := new(GroupingNode)
	for _, v := range visitable {
		nodes = append(nodes, node.NotEq(v))
	}
	if len(nodes) > 0 {
		// unshift first node
		m, nodes := nodes[0], nodes[1:]
		var memo Visitable = m
		for _, n := range nodes {
			memo = &OrNode{Left: memo, Right: n}
		}
		grouping.Expr = append(grouping.Expr, memo)
	}
	return grouping
}

func (node AttributeNode) NotEqAll(visitable ...Visitable) *GroupingNode {
	var nodes []Visitable
	grouping := new(GroupingNode)
	for _, v := range visitable {
		nodes = append(nodes, node.NotEq(v))
	}
	grouping.Expr = append(grouping.Expr, &AndNode{Children: &nodes})
	return grouping
}
<commit_msg>Implemented AttributeNode#GtAll<commit_after>package rel

type AttributeNode struct {
	Name     SqlLiteralNode
	Relation Visitable
	BaseVisitable
}

func NewAttributeNode(v Visitable, name string) AttributeNode {
	return AttributeNode{
		Name:     Sql(name),
		Relation: v,
	}
}

func (node AttributeNode) Eq(v Visitable) EqualityNode {
	return NewEqualityNode(node, v)
}

func (node AttributeNode) Lt(v Visitable) LessThanNode {
	return LessThanNode{Left: node, Right: v}
}

func (node AttributeNode) LtEq(v Visitable) *LessThanOrEqualNode {
	return &LessThanOrEqualNode{Left: node, Right: v}
}

func (node AttributeNode) Gt(v Visitable) *GreaterThanNode {
	return &GreaterThanNode{Left: node, Right: v}
}

func (node AttributeNode) GtAny(visitable ...Visitable) *GroupingNode {
	var nodes []*GreaterThanNode
	grouping := new(GroupingNode)
	for _, v := range visitable {
		nodes = append(nodes, node.Gt(v))
	}
	if len(nodes) > 0 {
		// unshift first node
		m, nodes := nodes[0], nodes[1:]
		var memo Visitable = m
		for _, n := range nodes {
			memo = &OrNode{Left: memo, Right: n}
		}
		grouping.Expr = append(grouping.Expr, memo)
	}
	return grouping
}

func (node AttributeNode) GtAll(visitable ...Visitable) *GroupingNode {
	var nodes []Visitable
	grouping := new(GroupingNode)
	for _, v := range visitable {
		nodes = append(nodes, node.Gt(v))
	}
	grouping.Expr = append(grouping.Expr, &AndNode{Children: &nodes})
	return grouping
}

func (node AttributeNode) GtEq(v Visitable) *GreaterThanOrEqualNode {
	return &GreaterThanOrEqualNode{Left: node, Right: v}
}

func (node AttributeNode) Desc() DescendingNode {
	return DescendingNode{Expr: node}
}

func (node AttributeNode) Asc() AscendingNode {
	return AscendingNode{Expr: node}
}

func (node AttributeNode) Count() CountNode {
	return CountNode{Expressions: node}
}

func (node AttributeNode) As(v Visitable) AsNode {
	return AsNode{
		Left:  node,
		Right: v,
	}
}

func (node AttributeNode) In(v Visitable) Visitable {
	var ret Visitable
	switch val := v.(type) {
	case SelectManager:
		ret = &InNode{Left: node, Right: val.Ast}
	default:
		ret = &InNode{Left: node, Right: v}
	}
	return ret
}

func (node AttributeNode) NotEq(v Visitable) *NotEqualNode {
	return &NotEqualNode{
		Left:  node,
		Right: v,
	}
}

func (node AttributeNode) NotEqual(v Visitable) *NotEqualNode {
	return node.NotEq(v)
}

func (node AttributeNode) NotEqAny(visitable ...Visitable) *GroupingNode {
	var nodes []*NotEqualNode
	grouping := new(GroupingNode)
	for _, v := range visitable {
		nodes = append(nodes, node.NotEq(v))
	}
	if len(nodes) > 0 {
		// unshift first node
		m, nodes := nodes[0], nodes[1:]
		var memo Visitable = m
		for _, n := range nodes {
			memo = &OrNode{Left: memo, Right: n}
		}
		grouping.Expr = append(grouping.Expr, memo)
	}
	return grouping
}

func (node AttributeNode) NotEqAll(visitable ...Visitable) *GroupingNode {
	var nodes []Visitable
	grouping := new(GroupingNode)
	for _, v := range visitable {
		nodes = append(nodes, node.NotEq(v))
	}
	grouping.Expr = append(grouping.Expr, &AndNode{Children: &nodes})
	return grouping
}
<|endoftext|>


<commit_before>package phpobject

import (
	"fmt"
	"io"
	"regexp"
)

type PValueType int

//r    zval *   资源（文件指针，数据库连接等）
//z    zval *   无任何操作的zval
const (
	PTNil PValueType = iota
	PTBool
	PTLong
	PTDouble
	PTString
	PTArray
	PTObject
)

var pValueNames = [9]string{"nil", "boolean", "long", "double", "string", "array", "object"}

func (vt PValueType) String() string {
	return pValueNames[int(vt)]
}

type PValue interface {
	String() string
	Type() PValueType
	serialize(w io.Writer)
	//unserialize(r io.Reader)
}

type PNilType struct{}

func (nl *PNilType) String() string        { return "nil" }
func (nl *PNilType) Type() PValueType      { return PTNil }
func (nl *PNilType) serialize(w io.Writer) {}

var PNil = PValue(&PNilType{})

type PBool bool

func (bl PBool) String() string {
	if bool(bl) {
		return "true"
	}
	return "false"
}
func (bl PBool) Type() PValueType { return PTBool }
func (bl PBool) serialize(w io.Writer) {
	if bl {
		w.Write([]byte("b:1;"))
	} else {
		w.Write([]byte("b:0;"))
	}
}

//if isinstance(obj, basestring):
//    encoded_obj = obj
//    if isinstance(obj, unicode):
//        encoded_obj = obj.encode(charset, errors)
//    s = BytesIO()
//    s.write(b's:')
//    s.write(str(len(encoded_obj)).encode('latin1'))
//    s.write(b':"')
//    s.write(encoded_obj)
//    s.write(b'";')
//    return s.getvalue()
//if isinstance(obj, (list, tuple, dict)):
//    out = []
//    if isinstance(obj, dict):
//        iterable = obj.items()
//    else:
//        iterable = enumerate(obj)
//    for key, value in iterable:
//        out.append(_serialize(key, True))
//        out.append(_serialize(value, False))
//    return b''.join([
//        b'a:',
//        str(len(obj)).encode('latin1'),
//        b':{',
//        b''.join(out),
//        b'}'
//    ])
//if isinstance(obj, phpobject):
//    return b'O' + _serialize(obj.__name__, True)[1:-1] + \
//           _serialize(obj.__php_vars__, False)[1:]
//if object_hook is not None:
//    return _serialize(object_hook(obj), False)
//raise TypeError('can\'t serialize %r' % type(obj))

var PTrue = PBool(true)
var PFalse = PBool(false)

type PLong int

func (lt PLong) String() string   { return fmt.Sprint(lt) }
func (lt PLong) Type() PValueType { return PTLong }
func (lt PLong) serialize(w io.Writer) {
	fmt.Fprintf(w, "i:%d;", lt)
}

type PDouble float64

func (dt PDouble) String() string   { return fmt.Sprint(dt) }
func (dt PDouble) Type() PValueType { return PTDouble }
func (dt PDouble) serialize(w io.Writer) {
	fmt.Fprintf(w, "d:%f;", dt)
}

type PString string

func (st PString) String() string   { return string(st) }
func (st PString) Type() PValueType { return PTString }
func (st PString) serialize(w io.Writer) {
	fmt.Fprintf(w, "s:%d:\"", len(st))
	fmt.Fprint(w, st)
	fmt.Fprint(w, "\";")
}

const (
	NumArray = 1
	KeyArray = 2
)

type PArray struct {
	array map[string]PValue
	//forceType int
}

func NewArray() *PArray {
	var at PArray
	at.array = make(map[string]PValue)
	return &at
}

func (tb *PArray) Iget(index int) (PValue, bool) {
	key := fmt.Sprintf("%d", index)
	v, o := tb.array[key]
	return v, o
}
func (tb *PArray) Rget(key string) (PValue, bool) {
	v, o := tb.array[key]
	return v, o
}
func (tb *PArray) Pget(key string) (PValue, bool) {
	v, o := tb.array[key]
	return v, o
}

func (tb *PArray) Iset(index int, value PValue) {
	key := fmt.Sprintf("%d", index)
	tb.array[key] = value
}
func (tb *PArray) Rset(key string, value PValue) {
	tb.array[key] = value
}
func (tb *PArray) Pset(key string, value PValue) string {
	tb.array[key] = value
	return key
}

var patNumber, _ = regexp.Compile(`^-?[1-9][0-9]*$`)

func serializeKey(w io.Writer, key string) {
	if key == "0" || patNumber.MatchString(key) {
		fmt.Fprintf(w, "i:%s;", key)
	} else {
		fmt.Fprintf(w, "s:%d:\"", len(key))
		fmt.Fprint(w, key)
		fmt.Fprint(w, "\";")
	}
}

func (tb *PArray) String() string   { return fmt.Sprintf("table: %p", tb) }
func (tb *PArray) Type() PValueType { return PTArray }
func (tb *PArray) serialize(w io.Writer) {
	fmt.Fprintf(w, "a:%d:{", len(tb.array))
	for k, v := range tb.array {
		serializeKey(w, k)
		v.serialize(w)
	}
	w.Write([]byte("}"))
}
func (tb *PArray) Output(w io.Writer) {
	tb.serialize(w)
}
<commit_msg>add object serialize<commit_after>package phpobject

import (
	"fmt"
	"io"
	"regexp"
)

type PValueType int

//r    zval *   资源（文件指针，数据库连接等）
//z    zval *   无任何操作的zval
const (
	PTNil PValueType = iota
	PTBool
	PTLong
	PTDouble
	PTString
	PTArray
	PTObject
)

var pValueNames = [9]string{"nil", "boolean", "long", "double", "string", "array", "object"}

func (vt PValueType) String() string {
	return pValueNames[int(vt)]
}

type PValue interface {
	String() string
	Type() PValueType
	serialize(w io.Writer)
	//unserialize(r io.Reader)
}

type PNilType struct{}

func (nl *PNilType) String() string        { return "nil" }
func (nl *PNilType) Type() PValueType      { return PTNil }
func (nl *PNilType) serialize(w io.Writer) {}

var PNil = PValue(&PNilType{})

type PBool bool

func (bl PBool) String() string {
	if bool(bl) {
		return "true"
	}
	return "false"
}
func (bl PBool) Type() PValueType { return PTBool }
func (bl PBool) serialize(w io.Writer) {
	if bl {
		w.Write([]byte("b:1;"))
	} else {
		w.Write([]byte("b:0;"))
	}
}

//if isinstance(obj, basestring):
//    encoded_obj = obj
//    if isinstance(obj, unicode):
//        encoded_obj = obj.encode(charset, errors)
//    s = BytesIO()
//    s.write(b's:')
//    s.write(str(len(encoded_obj)).encode('latin1'))
//    s.write(b':"')
//    s.write(encoded_obj)
//    s.write(b'";')
//    return s.getvalue()
//if isinstance(obj, (list, tuple, dict)):
//    out = []
//    if isinstance(obj, dict):
//        iterable = obj.items()
//    else:
//        iterable = enumerate(obj)
//    for key, value in iterable:
//        out.append(_serialize(key, True))
//        out.append(_serialize(value, False))
//    return b''.join([
//        b'a:',
//        str(len(obj)).encode('latin1'),
//        b':{',
//        b''.join(out),
//        b'}'
//    ])
//if isinstance(obj, phpobject):
//    return b'O' + _serialize(obj.__name__, True)[1:-1] + \
//           _serialize(obj.__php_vars__, False)[1:]
//if object_hook is not None:
//    return _serialize(object_hook(obj), False)
//raise TypeError('can\'t serialize %r' % type(obj))

var PTrue = PBool(true)
var PFalse = PBool(false)

type PLong int

func (lt PLong) String() string   { return fmt.Sprint(lt) }
func (lt PLong) Type() PValueType { return PTLong }
func (lt PLong) serialize(w io.Writer) {
	fmt.Fprintf(w, "i:%d;", lt)
}

type PDouble float64

func (dt PDouble) String() string   { return fmt.Sprint(dt) }
func (dt PDouble) Type() PValueType { return PTDouble }
func (dt PDouble) serialize(w io.Writer) {
	fmt.Fprintf(w, "d:%f;", dt)
}

type PString string

func (st PString) String() string   { return string(st) }
func (st PString) Type() PValueType { return PTString }
func (st PString) serialize(w io.Writer) {
	fmt.Fprintf(w, "s:%d:\"", len(st))
	fmt.Fprint(w, st)
	fmt.Fprint(w, "\";")
}

const (
	NumArray = 1
	KeyArray = 2
)

type PArray struct {
	array map[string]PValue
	//forceType int
}

func NewArray() *PArray {
	var at PArray
	at.array = make(map[string]PValue)
	return &at
}

func (tb *PArray) Iget(index int) (PValue, bool) {
	key := fmt.Sprintf("%d", index)
	v, o := tb.array[key]
	return v, o
}
func (tb *PArray) Rget(key string) (PValue, bool) {
	v, o := tb.array[key]
	return v, o
}
func (tb *PArray) Pget(key string) (PValue, bool) {
	v, o := tb.array[key]
	return v, o
}

func (tb *PArray) Iset(index int, value PValue) {
	key := fmt.Sprintf("%d", index)
	tb.array[key] = value
}
func (tb *PArray) Rset(key string, value PValue) {
	tb.array[key] = value
}
func (tb *PArray) Pset(key string, value PValue) string {
	tb.array[key] = value
	return key
}

var patNumber, _ = regexp.Compile(`^-?[1-9][0-9]*$`)

func serializeKey(w io.Writer, key string) {
	if key == "0" || patNumber.MatchString(key) {
		fmt.Fprintf(w, "i:%s;", key)
	} else {
		fmt.Fprintf(w, "s:%d:\"", len(key))
		fmt.Fprint(w, key)
		fmt.Fprint(w, "\";")
	}
}

func (tb *PArray) String() string   { return fmt.Sprintf("table: %v", tb) }
func (tb *PArray) Type() PValueType { return PTArray }
func (tb *PArray) serialize(w io.Writer) {
	fmt.Fprintf(w, "a:%d:{", len(tb.array))
	for k, v := range tb.array {
		serializeKey(w, k)
		v.serialize(w)
	}
	w.Write([]byte("}"))
}
func (tb *PArray) Output(w io.Writer) {
	tb.serialize(w)
}

type PObject struct {
	array map[string]PValue
	class string
	//forceType int
}

func NewObject(class string) *PObject {
	var ot PObject
	ot.array = make(map[string]PValue)
	ot.class = class
	return &ot
}

var patVarName, _ = regexp.Compile(`^[[:alpha:]_]\w*$`)

func (ot *PObject) String() string   { return fmt.Sprintf("object: %v", ot) }
func (ot *PObject) Type() PValueType { return PTObject }
func (ot *PObject) serialize(w io.Writer) {
	fmt.Fprintf(w, "O:%d:\"%s\"", len(st), ot.class)
	fmt.Fprintf(w, ":%d:{", len(tb.array))
	for k, v := range tb.array {
		kk := PString(k)
		kk.serialize(kk)
		v.serialize(w)
	}
	w.Write([]byte("}"))
}
<|endoftext|>


<commit_before>package models

var (
	accountCache map[int64]string
)

func init() {
	accountCache = make(map[int64]string)
}

func AccountOldIdById(id int64) (string, error) {
	if oldId, ok := accountCache[id]; ok {
		return oldId, nil
	}

	oldId, err := FetchOdlIdByAccountId(id)
	if err != nil {
		return "", err
	}

	accountCache[id] = oldId
	return oldId, nil
}
<commit_msg>Social: replace api ids with old account ids<commit_after>package models

var (
	accountCache map[int64]string
)

func init() {
	accountCache = make(map[int64]string)
}

func AccountOldIdById(id int64) (string, error) {
	if oldId, ok := accountCache[id]; ok {
		return oldId, nil
	}

	oldId, err := FetchOdlIdByAccountId(id)
	if err != nil {
		return "", err
	}

	accountCache[id] = oldId
	return oldId, nil
}

func AccountOldsIdByIds(ids []int64) ([]string, error) {
	oldIds := make([]string, len(ids))
	if len(oldIds) == 0 {
		return oldIds, nil
	}

	for i, id := range ids {
		oldId, err := AccountOldIdById(id)
		if err != nil {
			return oldIds, err
		}
		oldIds[i] = oldId
	}

	return oldIds, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"koding/db/mongodb/modelhelper"
	"socialapi/config"
	"testing"

	"github.com/koding/runner"
)

var (
	PARTICIPANT_COUNT = 4
)

func TestFrontpageListingOperations(t *testing.T) {

	r := runner.New("test")
	if err := r.Init(); err != nil {
		t.Fatalf("couldnt start bongo %s", err.Error())
	}
	defer r.Close()

	appConfig := config.MustRead(r.Conf.Path)
	modelhelper.Initialize(appConfig.Mongo)
	defer modelhelper.Close()

	testFrontpageOperations()
}

func testFrontpageOperations() {
	var accounts []*models.Account
	for i := 0; i < 2; i++ {
		account, err := models.CreateAccountInBothDbs()
		if err == nil {
			accounts = append(accounts, account)
		}
	}

	for i := 0; i < len(accounts); i++ {
		_, err := populateChannelwithAccount(accounts[i].Id)
		if err != nil {
			fmt.Println(err)
			return
		}
	}

	for i := 0; i < len(accounts); i++ {
		channels, err := rest.FetchChannels(accounts[i].Id)
		if err != nil {
			fmt.Println(err)
			return
		}
		for j := 0; j < len(channels); j++ {
			fetchHistoryAndCheckMessages(channels[j].Id, accounts[i])
		}
	}
}

func fetchHistoryAndCheckMessages(channelId int64, account *models.Account) {
	ses, err := models.FetchOrCreateSession(account.Nick)
	if err != nil {
		fmt.Println(err)
		return
	}

	history, err := rest.GetHistory(
		channelId,
		&request.Query{
			AccountId: account.Id,
		},
		ses.ClientId,
	)

	if err != nil {
		fmt.Println(err)
		return
	}

	if len(history.MessageList) != PARTICIPANT_COUNT {
		fmt.Println("history should have 4 messages", len(history.MessageList))
		return
	}

	for i := 0; i < len(history.MessageList); i++ {
		if len(history.MessageList[i].Replies) != PARTICIPANT_COUNT {
			fmt.Println("replies count should be PARTICIPANT_COUNT", len(history.MessageList[i].Replies))
		}
		if len(history.MessageList[i].Interactions) != 1 {
			fmt.Println("interaction count should be PARTICIPANT_COUNT", len(history.MessageList[i].Interactions))
		}
	}

	// fmt.Println(history.UnreadCount)
}

func populateChannelwithAccount(accountId int64) (*models.Channel, error) {
	channel, err := rest.CreateChannel(accountId)
	if err != nil {
		return nil, err
	}

	_, err = rest.AddChannelParticipant(channel.Id, accountId, accountId)
	if err != nil {
		return nil, err
	}

	participants, err := rest.CreateChannelParticipants(channel.Id, channel.CreatorId, PARTICIPANT_COUNT)
	if err != nil {
		return nil, err
	}

	//everyone will post status update
	for i := 0; i < len(participants); i++ {
		_, err := populatePost(channel.Id, participants[i].AccountId)
		if err != nil {
			return nil, err
		}
	}

	return channel, nil

}

func populatePost(channelId, accountId int64) (*models.ChannelMessage, error) {
	post, err := rest.CreatePost(channelId, accountId)
	if err != nil {
		return nil, err
	}

	participants, err := rest.CreateChannelParticipants(channelId, accountId, PARTICIPANT_COUNT)
	if err != nil {
		return nil, err
	}

	for i := 0; i < len(participants); i++ {
		reply, err := rest.AddReply(post.Id, participants[i].AccountId, post.InitialChannelId)
		if err != nil {
			return nil, err
		}

		// add likes to replies
		_, err = rest.AddInteraction("like", reply.Id, participants[i].AccountId)
		if err != nil {
			return nil, err
		}

		// like every comment
		_, err = rest.AddInteraction("like", reply.Id, accountId)
		if err != nil {
			return nil, err
		}

		// add likes to post
		_, err = rest.AddInteraction("like", post.Id, participants[i].AccountId)
		if err != nil {
			return nil, err
		}

	}

	// like your post
	_, err = rest.AddInteraction("like", post.Id, accountId)
	if err != nil {
		return nil, err
	}

	return post, nil
}
<commit_msg>Socialapi: add imports<commit_after>package main

import (
	"fmt"
	"koding/db/mongodb/modelhelper"
	"socialapi/config"
	"socialapi/models"
	"socialapi/request"
	"socialapi/rest"
	"testing"

	"github.com/koding/runner"
)

var (
	PARTICIPANT_COUNT = 4
)

func TestFrontpageListingOperations(t *testing.T) {

	r := runner.New("test")
	if err := r.Init(); err != nil {
		t.Fatalf("couldnt start bongo %s", err.Error())
	}
	defer r.Close()

	appConfig := config.MustRead(r.Conf.Path)
	modelhelper.Initialize(appConfig.Mongo)
	defer modelhelper.Close()

	testFrontpageOperations()
}

func testFrontpageOperations() {
	var accounts []*models.Account
	for i := 0; i < 2; i++ {
		account, err := models.CreateAccountInBothDbs()
		if err == nil {
			accounts = append(accounts, account)
		}
	}

	for i := 0; i < len(accounts); i++ {
		_, err := populateChannelwithAccount(accounts[i].Id)
		if err != nil {
			fmt.Println(err)
			return
		}
	}

	for i := 0; i < len(accounts); i++ {
		channels, err := rest.FetchChannels(accounts[i].Id)
		if err != nil {
			fmt.Println(err)
			return
		}
		for j := 0; j < len(channels); j++ {
			fetchHistoryAndCheckMessages(channels[j].Id, accounts[i])
		}
	}
}

func fetchHistoryAndCheckMessages(channelId int64, account *models.Account) {
	ses, err := models.FetchOrCreateSession(account.Nick)
	if err != nil {
		fmt.Println(err)
		return
	}

	history, err := rest.GetHistory(
		channelId,
		&request.Query{
			AccountId: account.Id,
		},
		ses.ClientId,
	)

	if err != nil {
		fmt.Println(err)
		return
	}

	if len(history.MessageList) != PARTICIPANT_COUNT {
		fmt.Println("history should have 4 messages", len(history.MessageList))
		return
	}

	for i := 0; i < len(history.MessageList); i++ {
		if len(history.MessageList[i].Replies) != PARTICIPANT_COUNT {
			fmt.Println("replies count should be PARTICIPANT_COUNT", len(history.MessageList[i].Replies))
		}
		if len(history.MessageList[i].Interactions) != 1 {
			fmt.Println("interaction count should be PARTICIPANT_COUNT", len(history.MessageList[i].Interactions))
		}
	}

	// fmt.Println(history.UnreadCount)
}

func populateChannelwithAccount(accountId int64) (*models.Channel, error) {
	channel, err := rest.CreateChannel(accountId)
	if err != nil {
		return nil, err
	}

	_, err = rest.AddChannelParticipant(channel.Id, accountId, accountId)
	if err != nil {
		return nil, err
	}

	participants, err := rest.CreateChannelParticipants(channel.Id, channel.CreatorId, PARTICIPANT_COUNT)
	if err != nil {
		return nil, err
	}

	//everyone will post status update
	for i := 0; i < len(participants); i++ {
		_, err := populatePost(channel.Id, participants[i].AccountId)
		if err != nil {
			return nil, err
		}
	}

	return channel, nil

}

func populatePost(channelId, accountId int64) (*models.ChannelMessage, error) {
	post, err := rest.CreatePost(channelId, accountId)
	if err != nil {
		return nil, err
	}

	participants, err := rest.CreateChannelParticipants(channelId, accountId, PARTICIPANT_COUNT)
	if err != nil {
		return nil, err
	}

	for i := 0; i < len(participants); i++ {
		reply, err := rest.AddReply(post.Id, participants[i].AccountId, post.InitialChannelId)
		if err != nil {
			return nil, err
		}

		// add likes to replies
		_, err = rest.AddInteraction("like", reply.Id, participants[i].AccountId)
		if err != nil {
			return nil, err
		}

		// like every comment
		_, err = rest.AddInteraction("like", reply.Id, accountId)
		if err != nil {
			return nil, err
		}

		// add likes to post
		_, err = rest.AddInteraction("like", post.Id, participants[i].AccountId)
		if err != nil {
			return nil, err
		}

	}

	// like your post
	_, err = rest.AddInteraction("like", post.Id, accountId)
	if err != nil {
		return nil, err
	}

	return post, nil
}
<|endoftext|>


<commit_before>package tumblr

import (
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestReadPostsFromCSV(t *testing.T) {
	posts := ReadPostsFromCSV(getCSVPath(true))
	assert.Equal(t, len(posts), 1)
	assert.Equal(t, posts[0].ID, int64(1234))
	assert.Equal(t, posts[0].Title, "title")
	assert.Equal(t, posts[0].URL, "url")
	assert.Equal(t, posts[0].Image, "http://static.reaction.pics/img/abcd.gif")
	assert.Equal(t, posts[0].Likes, int64(123))
}
<commit_msg>Add test<commit_after>package tumblr

import (
	"strings"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestReadPostsFromCSV(t *testing.T) {
	posts := ReadPostsFromCSV(getCSVPath(true))
	assert.Equal(t, len(posts), 1)
	assert.Equal(t, posts[0].ID, int64(1234))
	assert.Equal(t, posts[0].Title, "title")
	assert.Equal(t, posts[0].URL, "url")
	assert.Equal(t, posts[0].Image, "http://static.reaction.pics/img/abcd.gif")
	assert.Equal(t, posts[0].Likes, int64(123))
}

func TestReadPercentFromCSV(t *testing.T) {
	data := `1234,a% b,url,image,123`
	posts := readCSV(strings.NewReader(data))
	assert.Equal(t, posts[0].Title, "a% b")
}
<|endoftext|>


<commit_before>package memaccess

import (
	"bufio"
	"fmt"
	"os"
	"path/filepath"
	"strconv"
	"strings"
)

type process struct {
	pid          uint
	mapsFilepath string
	memFilepath  string
}

type mapInfo struct {
	start uintptr
	end   uintptr
}

func newProcessMemoryReaderImpl(pid uint) (process, error, []error) {
	var result process
	result.pid = pid
	result.mapsFilepath = filepath.Join("/proc", fmt.Sprintf("%d", pid), "maps")
	result.memFilepath = filepath.Join("/proc", fmt.Sprintf("%d", pid), "mem")
	// trying to open the maps file, only to see if gives an error
	f, harderror := os.Open(result.mapsFilepath)
	softerrors := make([]error, 0)
	if harderror != nil {
		return process{}, harderror, softerrors
	}
	f.Close()
	return result, nil, softerrors
}

func (p process) Close() (error, []error) {
	return nil, make([]error, 0)
}

// NextReadableMemoryRegion should return a MemoryRegion with address inside or,
// if that's impossible, the next readable MemoryRegion
func (p process) NextReadableMemoryRegion(address uintptr) (MemoryRegion, error, []error) {
	mapsFile, harderror := os.Open(p.mapsFilepath)
	softerrors := make([]error, 0)
	if harderror != nil {
		return MemoryRegion{}, harderror, softerrors
	}
	defer mapsFile.Close()

	path, harderror := pathByPID(p.pid)
	if harderror != nil {
		return MemoryRegion{}, harderror, softerrors
	}

	mappedAddresses, harderror := getMappedAddresses(mapsFile, path)
	if harderror != nil {
		return MemoryRegion{}, harderror, softerrors
	}

	mappedRegion, harderror := nextReadableMappedRegion(address, mappedAddresses)
	//TODO: ignore non readable mapped regions and add a softerror
	if harderror != nil {
		return NoRegionAvailable, harderror, softerrors
	}

	if mappedRegion.start != 0 {
		size := uint(mappedRegion.end - mappedRegion.start)
		return MemoryRegion{mappedRegion.start, size}, nil, softerrors
	}
	return NoRegionAvailable, nil, softerrors
}

func nextReadableMappedRegion(address uintptr, mappedAddresses []mapInfo) (mapInfo, error) {
	for _, mapinfo := range mappedAddresses {
		if mapinfo.start <= address && address < mapinfo.end {
			return mapinfo, nil
		}
	}
	// there's no mapped region with address inside it
	// I should return the next one
	for _, mapinfo := range mappedAddresses {
		if address < mapinfo.start {
			return mapinfo, nil
		}
	}
	// there's no mapped region with address inside it and no next region
	return mapInfo{}, nil
}

func getMappedAddresses(mapsFile *os.File, path string) ([]mapInfo, error) {
	res := make([]mapInfo, 0)
	scanner := bufio.NewScanner(mapsFile)
	goals := []string{"[heap]", "[stack]", path} // we want to look into the binary memory, its heap and its stack

	for scanner.Scan() {
		line := scanner.Text()

		items := strings.Split(line, " ")
		if len(items) <= 1 {
			continue
		}
		if stringInSlice(items[len(items)-1], goals) {
			fields := strings.Split(items[0], "-")
			start64, err := strconv.ParseUint(fields[0], 16, 64)
			if err != nil {
				return nil, err
			}
			end64, err := strconv.ParseUint(fields[1], 16, 64)
			if err != nil {
				return nil, err
			}
			start := uintptr(start64)
			end := uintptr(end64)
			info := mapInfo{start: start, end: end}
			res = append(res, info)
		}
	}
	if err := scanner.Err(); err != nil {
		return nil, err
	}
	return res, nil
}

func (p process) CopyMemory(address uintptr, buffer []byte) (error, []error) {
	mem, harderror := os.Open(p.memFilepath)
	softerrors := make([]error, 0)
	if harderror != nil {
		//TODO(laski): add address to error string
		return harderror, softerrors
	}
	defer mem.Close()
	bytes_read, harderror := mem.ReadAt(buffer, int64(address))
	if bytes_read != len(buffer) {
		return fmt.Errorf("Coul not read the entire buffer"), softerrors
	}
	if harderror != nil {
		return harderror, softerrors
	}
	return nil, softerrors
}

func pathByPID(pid uint) (string, error) {
	// the file /proc/[pid]/exe is a link to the binary
	path := filepath.Join("/proc", fmt.Sprintf("%d", pid), "exe")
	res, err := os.Readlink(path)
	if err != nil {
		return "", err
	}
	return res, nil
}

func stringInSlice(a string, list []string) bool {
	for _, b := range list {
		if a == b {
			return true
		}
	}
	return false
}
<commit_msg>[memaccess] Better errors on linux's CopyMemory<commit_after>package memaccess

import (
	"bufio"
	"fmt"
	"os"
	"path/filepath"
	"strconv"
	"strings"
)

type process struct {
	pid          uint
	mapsFilepath string
	memFilepath  string
}

type mapInfo struct {
	start uintptr
	end   uintptr
}

func newProcessMemoryReaderImpl(pid uint) (process, error, []error) {
	var result process
	result.pid = pid
	result.mapsFilepath = filepath.Join("/proc", fmt.Sprintf("%d", pid), "maps")
	result.memFilepath = filepath.Join("/proc", fmt.Sprintf("%d", pid), "mem")
	// trying to open the maps file, only to see if gives an error
	f, harderror := os.Open(result.mapsFilepath)
	softerrors := make([]error, 0)
	if harderror != nil {
		return process{}, harderror, softerrors
	}
	f.Close()
	return result, nil, softerrors
}

func (p process) Close() (error, []error) {
	return nil, make([]error, 0)
}

// NextReadableMemoryRegion should return a MemoryRegion with address inside or,
// if that's impossible, the next readable MemoryRegion
func (p process) NextReadableMemoryRegion(address uintptr) (MemoryRegion, error, []error) {
	mapsFile, harderror := os.Open(p.mapsFilepath)
	softerrors := make([]error, 0)
	if harderror != nil {
		return MemoryRegion{}, harderror, softerrors
	}
	defer mapsFile.Close()

	path, harderror := pathByPID(p.pid)
	if harderror != nil {
		return MemoryRegion{}, harderror, softerrors
	}

	mappedAddresses, harderror := getMappedAddresses(mapsFile, path)
	if harderror != nil {
		return MemoryRegion{}, harderror, softerrors
	}

	mappedRegion, harderror := nextReadableMappedRegion(address, mappedAddresses)
	//TODO: ignore non readable mapped regions and add a softerror
	if harderror != nil {
		return NoRegionAvailable, harderror, softerrors
	}

	if mappedRegion.start != 0 {
		size := uint(mappedRegion.end - mappedRegion.start)
		return MemoryRegion{mappedRegion.start, size}, nil, softerrors
	}
	return NoRegionAvailable, nil, softerrors
}

func nextReadableMappedRegion(address uintptr, mappedAddresses []mapInfo) (mapInfo, error) {
	for _, mapinfo := range mappedAddresses {
		if mapinfo.start <= address && address < mapinfo.end {
			return mapinfo, nil
		}
	}
	// there's no mapped region with address inside it
	// I should return the next one
	for _, mapinfo := range mappedAddresses {
		if address < mapinfo.start {
			return mapinfo, nil
		}
	}
	// there's no mapped region with address inside it and no next region
	return mapInfo{}, nil
}

func getMappedAddresses(mapsFile *os.File, path string) ([]mapInfo, error) {
	res := make([]mapInfo, 0)
	scanner := bufio.NewScanner(mapsFile)
	goals := []string{"[heap]", "[stack]", path} // we want to look into the binary memory, its heap and its stack

	for scanner.Scan() {
		line := scanner.Text()

		items := strings.Split(line, " ")
		if len(items) <= 1 {
			continue
		}
		if stringInSlice(items[len(items)-1], goals) {
			fields := strings.Split(items[0], "-")
			start64, err := strconv.ParseUint(fields[0], 16, 64)
			if err != nil {
				return nil, err
			}
			end64, err := strconv.ParseUint(fields[1], 16, 64)
			if err != nil {
				return nil, err
			}
			start := uintptr(start64)
			end := uintptr(end64)
			info := mapInfo{start: start, end: end}
			res = append(res, info)
		}
	}
	if err := scanner.Err(); err != nil {
		return nil, err
	}
	return res, nil
}

func (p process) CopyMemory(address uintptr, buffer []byte) (error, []error) {
	mem, harderror := os.Open(p.memFilepath)
	softerrors := make([]error, 0)
	if harderror != nil {
		harderror := fmt.Errorf("Error while reading %d bytes starting at %x: %s", len(buffer), address, harderror)
		return harderror, softerrors
	}
	defer mem.Close()

	bytes_read, harderror := mem.ReadAt(buffer, int64(address))
	if bytes_read != len(buffer) {
		return fmt.Errorf("Coul not read the entire buffer"), softerrors
	}
	if harderror != nil {
		return harderror, softerrors
	}
	return nil, softerrors
}

func pathByPID(pid uint) (string, error) {
	// the file /proc/[pid]/exe is a link to the binary
	path := filepath.Join("/proc", fmt.Sprintf("%d", pid), "exe")
	res, err := os.Readlink(path)
	if err != nil {
		return "", err
	}
	return res, nil
}

func stringInSlice(a string, list []string) bool {
	for _, b := range list {
		if a == b {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>package main

import (
  "log"
  "github.com/gorilla/mux"
  "net/http"
  "net/http/httputil"
  "net/url"
  "github.com/fhs/gompd/mpd"
  "github.com/ascherkus/go-id3/src/id3"
  "os"
  "fmt"
  "encoding/json"
)

// TODO: consider if global is really the best idea, or if we should
//       make some classes, or something...
var mpd_conn *mpd.Client

func main() {
  mpdConnect("localhost:6600")

  // create a new mux router for our server.
  r := mux.NewRouter()

  // requests to `/stream` are proxied to the MPD httpd.
  r.HandleFunc("/stream",
    httputil.NewSingleHostReverseProxy(
      &url.URL{
        Scheme:"http",
        Host: "localhost:8000",
        Path: "/",
      }).ServeHTTP)

  r.HandleFunc("/songs", listSongs)
  r.HandleFunc("/current", getCurrentSong)

  // This MUST go last! It takes precidence over any after it, meaning
  // the server will try to serve a file, which most likely doesn't exist,
  // and will 404.
  //
  // serve up the frontend files.
  r.PathPrefix("/").Handler(http.FileServer(http.Dir("../frontend/turbo_wookie/web")))

  // sit, waiting, like a hunter, spying on its prey.
  log.Println("Starting server on port 9000")
  http.ListenAndServe(":9000", r)
}

/********************
  Handler Functions
 ********************/

// return all songs known to MPD to the client.
func listSongs(w http.ResponseWriter, r *http.Request) {
  // get all files from MPD
  mpdfiles, err := mpd_conn.GetFiles()
  if err != nil {
    log.Println("Couldn't get a list of files...")
    log.Fatal(err)
  }

  // create a slice of id3.File s
  files := make([]*id3.File, 0)

  for _, song := range mpdfiles {
    // grab the file on the filesystem
    file, err := os.Open("mpd/music/" + song)
    if err != nil {
      log.Println("Couldn't open file: " + song)
      log.Fatal(err)
    }

    // add the current file to our slice
    id3_file := id3.Read(file)
    files = append(files, id3_file)
  }

  // send the json to the client.
  fmt.Fprintf(w, jsoniffy(files_json))
}

// Return a JSON representation of the currently playing song.
func getCurrentSong(w http.ResponseWriter, r *http.Request) {
  currentSong, err := mpd_conn.CurrentSong()
  if err != nil {
    log.Println("Couldn't get current song info")
    log.Fatal(err)
  }

  fmt.Fprintf(w, jsoniffy(currentSong))
}

/*******************
  Helper Functions
 *******************/

// Connect to MPD's control channel, and set the global mpd_conn to it.
func mpdConnect(url string) {
  conn, err := mpd.Dial("tcp", url)

  // if we can't connect to MPD everything's fucked, nothing's going to work
  // kill all humans, and die, respectfully, after explaining what the issue
  // is.
  if err != nil {
    log.Println("\n\nServer quiting because it can't connect to MPD");
    log.Fatal(err)
    return
  }
  defer conn.Close()

  // set global mpd_conn to our new connection.
  mpd_conn = conn
}

// turn anything into JSON.
func jsoniffy(v interface {}) string {
  obj, err := json.MarshalIndent(v, "", "  ")
  if err != nil {
    log.Print("Couldn't turn something into JSON: ", v)
    log.Fatal(err)
  }

  return string(obj)
}<commit_msg>whoops<commit_after>package main

import (
  "log"
  "github.com/gorilla/mux"
  "net/http"
  "net/http/httputil"
  "net/url"
  "github.com/fhs/gompd/mpd"
  "github.com/ascherkus/go-id3/src/id3"
  "os"
  "fmt"
  "encoding/json"
)

// TODO: consider if global is really the best idea, or if we should
//       make some classes, or something...
var mpd_conn *mpd.Client

func main() {
  mpdConnect("localhost:6600")

  // create a new mux router for our server.
  r := mux.NewRouter()

  // requests to `/stream` are proxied to the MPD httpd.
  r.HandleFunc("/stream",
    httputil.NewSingleHostReverseProxy(
      &url.URL{
        Scheme:"http",
        Host: "localhost:8000",
        Path: "/",
      }).ServeHTTP)

  r.HandleFunc("/songs", listSongs)
  r.HandleFunc("/current", getCurrentSong)

  // This MUST go last! It takes precidence over any after it, meaning
  // the server will try to serve a file, which most likely doesn't exist,
  // and will 404.
  //
  // serve up the frontend files.
  r.PathPrefix("/").Handler(http.FileServer(http.Dir("../frontend/turbo_wookie/web")))

  // sit, waiting, like a hunter, spying on its prey.
  log.Println("Starting server on port 9000")
  http.ListenAndServe(":9000", r)
}

/********************
  Handler Functions
 ********************/

// return all songs known to MPD to the client.
func listSongs(w http.ResponseWriter, r *http.Request) {
  // get all files from MPD
  mpdfiles, err := mpd_conn.GetFiles()
  if err != nil {
    log.Println("Couldn't get a list of files...")
    log.Fatal(err)
  }

  // create a slice of id3.File s
  files := make([]*id3.File, 0)

  for _, song := range mpdfiles {
    // grab the file on the filesystem
    file, err := os.Open("mpd/music/" + song)
    if err != nil {
      log.Println("Couldn't open file: " + song)
      log.Fatal(err)
    }

    // add the current file to our slice
    id3_file := id3.Read(file)
    files = append(files, id3_file)
  }

  // send the json to the client.
  fmt.Fprintf(w, jsoniffy(files))
}

// Return a JSON representation of the currently playing song.
func getCurrentSong(w http.ResponseWriter, r *http.Request) {
  currentSong, err := mpd_conn.CurrentSong()
  if err != nil {
    log.Println("Couldn't get current song info")
    log.Fatal(err)
  }

  fmt.Fprintf(w, jsoniffy(currentSong))
}

/*******************
  Helper Functions
 *******************/

// Connect to MPD's control channel, and set the global mpd_conn to it.
func mpdConnect(url string) {
  conn, err := mpd.Dial("tcp", url)

  // if we can't connect to MPD everything's fucked, nothing's going to work
  // kill all humans, and die, respectfully, after explaining what the issue
  // is.
  if err != nil {
    log.Println("\n\nServer quiting because it can't connect to MPD");
    log.Fatal(err)
    return
  }
  defer conn.Close()

  // set global mpd_conn to our new connection.
  mpd_conn = conn
}

// turn anything into JSON.
func jsoniffy(v interface {}) string {
  obj, err := json.MarshalIndent(v, "", "  ")
  if err != nil {
    log.Print("Couldn't turn something into JSON: ", v)
    log.Fatal(err)
  }

  return string(obj)
}<|endoftext|>