<commit_before>package main

import (
	"encoding/json"
	"github.com/joinmytalk/xlog"
	"github.com/russross/meddler"
	"net/http"
	"time"
)

type Session struct {
	ID       int       `meddler:"id,pk" json:"-"`
	UploadID int       `meddler:"upload_id" json:"-"`
	PublicID string    `meddler:"public_id" json:"_id"`
	Started  time.Time `meddler:"started,utctimez" json:"started"`
	Ended    time.Time `meddler:"ended,utctimez" json:"ended,omitempty"`
}

func StartSession(w http.ResponseWriter, r *http.Request) {
	session, _ := store.Get(r, SESSION_NAME)

	if session.Values["gplusID"] == nil {
		http.Error(w, "authentication required", http.StatusForbidden)
		return
	}

	data := struct {
		UploadID string `json:"upload_id"`
	}{}

	if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
		xlog.Errorf("Decoding POST body failed: %v", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	var uploadEntry Upload

	if err := meddler.QueryRow(sqlDB, &uploadEntry, "select id from uploads where public_id = ? and owner = ?", data.UploadID, session.Values["gplusID"]); err != nil {
		xlog.Errorf("Querying upload %s failed: %v", data.UploadID, err)
		http.Error(w, err.Error(), http.StatusNotFound)
		return
	}

	id := generateID()

	if err := meddler.Insert(sqlDB, "sessions", &Session{
		UploadID: uploadEntry.ID,
		PublicID: id,
		Started:  time.Now(),
	}); err != nil {
		xlog.Errorf("Insert failed: %v", err)
		http.Error(w, "insert failed", http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(map[string]string{"id": id})
}

func GetSessions(w http.ResponseWriter, r *http.Request) {
	session, _ := store.Get(r, SESSION_NAME)

	if session.Values["gplusID"] == nil {
		http.Error(w, "authentication required", http.StatusForbidden)
		return
	}

	result := []*struct {
		PublicID string    `meddler:"public_id" json:"_id"`
		Title    string    `meddler:"title" json:"title"`
		Started  time.Time `meddler:"started,utctimez" json:"started"`
		Ended    time.Time `meddler:"ended,utctimez" json:"ended,omitempty"`
	}{}

	if err := meddler.QueryAll(sqlDB, &result, "select sessions.public_id as public_id, sessions.started as started, sessions.ended as ended, uploads.title as title  from uploads, sessions where sessions.upload_id = uploads.id and uploads.owner = ? order by sessions.started desc", session.Values["gplusID"]); err != nil {
		xlog.Errorf("Querying sessions failed: %v", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(result)
}

func SessionInfo(w http.ResponseWriter, r *http.Request) {
	session, _ := store.Get(r, SESSION_NAME)

	if session.Values["gplusID"] == nil {
		http.Error(w, "authentication required", http.StatusForbidden)
		return
	}

	id := r.URL.Query().Get(":id")

	result := struct {
		Title    string `meddler:"title" json:"title"`
		UploadID string `meddler:"public_id" json:"upload_id"`
		IsOwner  bool   `json:"owner" meddler:"-"`
		Owner    string `meddler:"owner" json:"-"`
		//Page int `json:"page"`
	}{}

	if err := meddler.QueryRow(sqlDB, &result,
		`SELECT 
			uploads.title AS title, 
			uploads.public_id AS public_id, 
			uploads.owner AS owner
			FROM uploads, sessions
			WHERE sessions.upload_id = uploads.id AND
				sessions.public_id = ?`, id); err != nil {
		xlog.Errorf("Loading session information failed: %v", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	result.IsOwner = (result.Owner == session.Values["gplusID"].(string))

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(result)
}

func StopSession(w http.ResponseWriter, r *http.Request) {
	session, _ := store.Get(r, SESSION_NAME)

	if session.Values["gplusID"] == nil {
		http.Error(w, "authentication required", http.StatusForbidden)
		return
	}

	requestData := struct {
		PublicID string `json:"session_id"`
	}{}

	if err := json.NewDecoder(r.Body).Decode(&requestData); err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	ownerData := struct {
		Owner string `json:"owner"`
	}{}

	if err := meddler.QueryRow(sqlDB, &ownerData, "SELECT uploads.owner AS owner FROM uploads, sessions WHERE sessions.public_id = ? AND sessions.upload_id = uploads.id LIMIT 1", requestData.PublicID); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if ownerData.Owner != session.Values["gplusID"].(string) {
		http.Error(w, "Unauthorized", http.StatusUnauthorized)
		return
	}

	sqlDB.Exec("UPDATE sessions SET ended = NOW() WHERE public_id = ?", requestData.PublicID)

	w.WriteHeader(http.StatusNoContent)
}

func DeleteSession(w http.ResponseWriter, r *http.Request) {
	session, _ := store.Get(r, SESSION_NAME)

	if session.Values["gplusID"] == nil {
		http.Error(w, "authentication required", http.StatusForbidden)
		return
	}

	requestData := struct {
		PublicID string `json:"session_id"`
	}{}

	if err := json.NewDecoder(r.Body).Decode(&requestData); err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	ownerData := struct {
		Owner string `meddler:"owner"`
	}{}

	if err := meddler.QueryRow(sqlDB, &ownerData, "SELECT uploads.owner AS owner FROM uploads, sessions WHERE sessions.public_id = ? AND sessions.upload_id = uploads.id LIMIT 1", requestData.PublicID); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if ownerData.Owner != session.Values["gplusID"].(string) {
		http.Error(w, "Unauthorized", http.StatusUnauthorized)
		return
	}

	sqlDB.Exec("DELETE FROM sessions WHERE public_id = ?", requestData.PublicID)

	w.WriteHeader(http.StatusNoContent)
}
<commit_msg>fix ended date issue.<commit_after>package main

import (
	"encoding/json"
	"github.com/joinmytalk/xlog"
	"github.com/russross/meddler"
	"net/http"
	"time"
)

type Session struct {
	ID       int       `meddler:"id,pk" json:"-"`
	UploadID int       `meddler:"upload_id" json:"-"`
	PublicID string    `meddler:"public_id" json:"_id"`
	Started  time.Time `meddler:"started,utctimez" json:"started"`
	Ended    time.Time `meddler:"ended,utctimez" json:"ended,omitempty"`
}

func StartSession(w http.ResponseWriter, r *http.Request) {
	session, _ := store.Get(r, SESSION_NAME)

	if session.Values["gplusID"] == nil {
		http.Error(w, "authentication required", http.StatusForbidden)
		return
	}

	data := struct {
		UploadID string `json:"upload_id"`
	}{}

	if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
		xlog.Errorf("Decoding POST body failed: %v", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	var uploadEntry Upload

	if err := meddler.QueryRow(sqlDB, &uploadEntry, "select id from uploads where public_id = ? and owner = ?", data.UploadID, session.Values["gplusID"]); err != nil {
		xlog.Errorf("Querying upload %s failed: %v", data.UploadID, err)
		http.Error(w, err.Error(), http.StatusNotFound)
		return
	}

	id := generateID()

	if err := meddler.Insert(sqlDB, "sessions", &Session{
		UploadID: uploadEntry.ID,
		PublicID: id,
		Started:  time.Now(),
	}); err != nil {
		xlog.Errorf("Insert failed: %v", err)
		http.Error(w, "insert failed", http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(map[string]string{"id": id})
}

func GetSessions(w http.ResponseWriter, r *http.Request) {
	session, _ := store.Get(r, SESSION_NAME)

	if session.Values["gplusID"] == nil {
		http.Error(w, "authentication required", http.StatusForbidden)
		return
	}

	result := []*struct {
		PublicID  string    `meddler:"public_id" json:"_id"`
		Title     string    `meddler:"title" json:"title"`
		Started   time.Time `meddler:"started,utctimez" json:"started"`
		Ended     time.Time `meddler:"ended,utctimez" json:"-"`
		EndedJSON string    `meddler:"-" json:"ended,omitempty"`
	}{}

	if err := meddler.QueryAll(sqlDB, &result, "select sessions.public_id as public_id, sessions.started as started, sessions.ended as ended, uploads.title as title  from uploads, sessions where sessions.upload_id = uploads.id and uploads.owner = ? order by sessions.started desc", session.Values["gplusID"]); err != nil {
		xlog.Errorf("Querying sessions failed: %v", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	// XXX: ugly hack.
	for _, entry := range result {
		formatted := entry.Ended.Format(time.RFC3339)
		if formatted != "0001-01-01T00:00:00Z" {
			entry.EndedJSON = formatted
		}
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(result)
}

func SessionInfo(w http.ResponseWriter, r *http.Request) {
	session, _ := store.Get(r, SESSION_NAME)

	if session.Values["gplusID"] == nil {
		http.Error(w, "authentication required", http.StatusForbidden)
		return
	}

	id := r.URL.Query().Get(":id")

	result := struct {
		Title    string `meddler:"title" json:"title"`
		UploadID string `meddler:"public_id" json:"upload_id"`
		IsOwner  bool   `json:"owner" meddler:"-"`
		Owner    string `meddler:"owner" json:"-"`
		//Page int `json:"page"`
	}{}

	if err := meddler.QueryRow(sqlDB, &result,
		`SELECT 
			uploads.title AS title, 
			uploads.public_id AS public_id, 
			uploads.owner AS owner
			FROM uploads, sessions
			WHERE sessions.upload_id = uploads.id AND
				sessions.public_id = ?`, id); err != nil {
		xlog.Errorf("Loading session information failed: %v", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	result.IsOwner = (result.Owner == session.Values["gplusID"].(string))

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(result)
}

func StopSession(w http.ResponseWriter, r *http.Request) {
	session, _ := store.Get(r, SESSION_NAME)

	if session.Values["gplusID"] == nil {
		http.Error(w, "authentication required", http.StatusForbidden)
		return
	}

	requestData := struct {
		PublicID string `json:"session_id"`
	}{}

	if err := json.NewDecoder(r.Body).Decode(&requestData); err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	ownerData := struct {
		Owner string `meddler:"owner"`
	}{}

	if err := meddler.QueryRow(sqlDB, &ownerData, "SELECT uploads.owner AS owner FROM uploads, sessions WHERE sessions.public_id = ? AND sessions.upload_id = uploads.id LIMIT 1", requestData.PublicID); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if ownerData.Owner != session.Values["gplusID"].(string) {
		http.Error(w, "Unauthorized", http.StatusUnauthorized)
		return
	}

	sqlDB.Exec("UPDATE sessions SET ended = NOW() WHERE public_id = ?", requestData.PublicID)

	w.WriteHeader(http.StatusNoContent)
}

func DeleteSession(w http.ResponseWriter, r *http.Request) {
	session, _ := store.Get(r, SESSION_NAME)

	if session.Values["gplusID"] == nil {
		http.Error(w, "authentication required", http.StatusForbidden)
		return
	}

	requestData := struct {
		PublicID string `json:"session_id"`
	}{}

	if err := json.NewDecoder(r.Body).Decode(&requestData); err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	ownerData := struct {
		Owner string `meddler:"owner"`
	}{}

	if err := meddler.QueryRow(sqlDB, &ownerData, "SELECT uploads.owner AS owner FROM uploads, sessions WHERE sessions.public_id = ? AND sessions.upload_id = uploads.id LIMIT 1", requestData.PublicID); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if ownerData.Owner != session.Values["gplusID"].(string) {
		http.Error(w, "Unauthorized", http.StatusUnauthorized)
		return
	}

	sqlDB.Exec("DELETE FROM sessions WHERE public_id = ?", requestData.PublicID)

	w.WriteHeader(http.StatusNoContent)
}

{'fraction_non_alphanumeric': 0.15299203254788948, 'fraction_numerical': 0.0018647228343787084, 'mean_word_length': 4.576086956521739, 'pattern_counts': {'":': 4, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1109911', 'n_tokens_mistral': 4303, 'n_tokens_neox': 4068, 'n_words': 887}