Using a web template
This commit is contained in:
parent
ef0d9691b8
commit
dbc58bd95b
|
@ -171,13 +171,7 @@ func add(user *gumble.User, url string) error {
|
||||||
dj.SendPrivateMessage(user, NO_ARGUMENT_MSG)
|
dj.SendPrivateMessage(user, NO_ARGUMENT_MSG)
|
||||||
return errors.New("NO_ARGUMENT")
|
return errors.New("NO_ARGUMENT")
|
||||||
} else {
|
} else {
|
||||||
title, err := findServiceAndAdd(user, url)
|
return findServiceAndAdd(user, url)
|
||||||
if err == nil {
|
|
||||||
dj.client.Self.Channel.Send(fmt.Sprintf(SONG_ADDED_HTML, user.Name, title), false)
|
|
||||||
} else {
|
|
||||||
dj.SendPrivateMessage(user, err.Error())
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
28
index.html
28
index.html
|
@ -2,17 +2,37 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="ISO-8859-1">
|
<meta charset="ISO-8859-1">
|
||||||
<title>%s - mumbledj</title>
|
<title>{{user}} - mumbledj</title>
|
||||||
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
function addURL(url) {
|
function api(type) {
|
||||||
|
return "{{.siteURL}}" + type + "?token={{.token}}";
|
||||||
|
}
|
||||||
|
|
||||||
|
function addURL() {
|
||||||
|
var url = $("#textbox");
|
||||||
|
$.ajax(api("add") + "&value=" + url.value);
|
||||||
|
url.value = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function volume() {
|
||||||
|
var volume = $("#textbox");
|
||||||
|
$.ajax(api("volume") + "&value=" + volume.value);
|
||||||
|
volume.value = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function skip(val) {
|
||||||
|
$.ajax(api("skip") + "&value=" + val);
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>Add Song Form</h1>
|
<h1>Add Song Form</h1>
|
||||||
<input type="text"/>
|
<input id="textbox" type="text"/>
|
||||||
<input type="button" value="Add Song" />
|
<input id="add" type="button" value="Add Song" onclick="addURL()"/>
|
||||||
|
<input id="volume" type="button" value="Set Volume" onclick="volume()"/>
|
||||||
|
<input id="skipSong" type="button" value="Skip Current Song" onclick="skip('song')"/>
|
||||||
|
<input id="skipPlaylist" type="button" value="Skip Current Playlist" onclick="skip('playlist')"/>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
13
main.go
13
main.go
|
@ -152,6 +152,17 @@ func isNil(a interface{}) bool {
|
||||||
return a == nil || reflect.ValueOf(a).IsNil()
|
return a == nil || reflect.ValueOf(a).IsNil()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RegexpFromURL(url string, patterns []string) *regexp.Regexp {
|
||||||
|
for _, pattern := range patterns {
|
||||||
|
if re, err := regexp.Compile(pattern); err == nil {
|
||||||
|
if re.MatchString(url) {
|
||||||
|
return re
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// dj variable declaration. This is done outside of main() to allow global use.
|
// dj variable declaration. This is done outside of main() to allow global use.
|
||||||
var dj = mumbledj{
|
var dj = mumbledj{
|
||||||
keepAlive: make(chan bool),
|
keepAlive: make(chan bool),
|
||||||
|
@ -230,7 +241,7 @@ func main() {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
Webserver()
|
Webserver(9563)
|
||||||
|
|
||||||
<-dj.keepAlive
|
<-dj.keepAlive
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ type Playlist interface {
|
||||||
|
|
||||||
var services = []Service{YouTube{}}
|
var services = []Service{YouTube{}}
|
||||||
|
|
||||||
func findServiceAndAdd(user *gumble.User, url string) (string, error) {
|
func findServiceAndAdd(user *gumble.User, url string) error {
|
||||||
var urlService Service
|
var urlService Service
|
||||||
|
|
||||||
// Checks all services to see if any can take the URL
|
// Checks all services to see if any can take the URL
|
||||||
|
@ -69,7 +69,9 @@ func findServiceAndAdd(user *gumble.User, url string) (string, error) {
|
||||||
oldLength := dj.queue.Len()
|
oldLength := dj.queue.Len()
|
||||||
var title string
|
var title string
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if title, err = urlService.NewRequest(user, url); err == nil {
|
if title, err = urlService.NewRequest(user, url); err == nil {
|
||||||
|
dj.client.Self.Channel.Send(fmt.Sprintf(SONG_ADDED_HTML, user.Name, title), false)
|
||||||
|
|
||||||
// Starts playing the new song if nothing else is playing
|
// Starts playing the new song if nothing else is playing
|
||||||
if oldLength == 0 && dj.queue.Len() != 0 && !dj.audioStream.IsPlaying() {
|
if oldLength == 0 && dj.queue.Len() != 0 && !dj.audioStream.IsPlaying() {
|
||||||
|
@ -81,7 +83,9 @@ func findServiceAndAdd(user *gumble.User, url string) (string, error) {
|
||||||
return "", errors.New("FAILED_TO_DOWNLOAD")
|
return "", errors.New("FAILED_TO_DOWNLOAD")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
dj.SendPrivateMessage(user, err.Error())
|
||||||
}
|
}
|
||||||
return title, err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,64 +35,13 @@ var youtubeVideoPatterns = []string{
|
||||||
`https?:\/\/www.youtube.com\/v\/([\w-]+)(\?t=\d*m?\d*s?)?`,
|
`https?:\/\/www.youtube.com\/v\/([\w-]+)(\?t=\d*m?\d*s?)?`,
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------
|
// ------
|
||||||
// YOUTUBE SERVICE
|
// TYPES
|
||||||
// ---------------
|
// ------
|
||||||
|
|
||||||
|
// YouTube implements the Service interface
|
||||||
type YouTube struct{}
|
type YouTube struct{}
|
||||||
|
|
||||||
// Name of the service
|
|
||||||
func (y YouTube) ServiceName() string {
|
|
||||||
return "Youtube"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks to see if service will accept URL
|
|
||||||
func (y YouTube) URLRegex(url string) bool {
|
|
||||||
return RegexpFromURL(url, append(youtubeVideoPatterns, []string{youtubePlaylistPattern}...)) != nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func RegexpFromURL(url string, patterns []string) *regexp.Regexp {
|
|
||||||
for _, pattern := range patterns {
|
|
||||||
if re, err := regexp.Compile(pattern); err == nil {
|
|
||||||
if re.MatchString(url) {
|
|
||||||
return re
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creates the requested song/playlist and adds to the queue
|
|
||||||
func (y YouTube) NewRequest(user *gumble.User, url string) (string, error) {
|
|
||||||
var shortURL, startOffset = "", ""
|
|
||||||
if re, err := regexp.Compile(youtubePlaylistPattern); err == nil {
|
|
||||||
if re.MatchString(url) {
|
|
||||||
if dj.HasPermission(user.Name, dj.conf.Permissions.AdminAddPlaylists) {
|
|
||||||
shortURL = re.FindStringSubmatch(url)[1]
|
|
||||||
playlist, err := NewYouTubePlaylist(user.Name, shortURL)
|
|
||||||
return playlist.Title(), err
|
|
||||||
} else {
|
|
||||||
return "", errors.New("NO_PLAYLIST_PERMISSION")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
re = RegexpFromURL(url, youtubeVideoPatterns)
|
|
||||||
matches := re.FindAllStringSubmatch(url, -1)
|
|
||||||
shortURL = matches[0][1]
|
|
||||||
if len(matches[0]) == 3 {
|
|
||||||
startOffset = matches[0][2]
|
|
||||||
}
|
|
||||||
song, err := NewYouTubeSong(user.Name, shortURL, startOffset, nil)
|
|
||||||
return song.Title(), err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------
|
|
||||||
// YOUTUBE SONG
|
|
||||||
// ------------
|
|
||||||
|
|
||||||
// YouTubeSong holds the metadata for a song extracted from a YouTube video.
|
// YouTubeSong holds the metadata for a song extracted from a YouTube video.
|
||||||
type YouTubeSong struct {
|
type YouTubeSong struct {
|
||||||
submitter string
|
submitter string
|
||||||
|
@ -107,14 +56,61 @@ type YouTubeSong struct {
|
||||||
dontSkip bool
|
dontSkip bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewYouTubeSong gathers the metadata for a song extracted from a YouTube video, and returns
|
// YouTubePlaylist holds the metadata for a YouTube playlist.
|
||||||
|
type YouTubePlaylist struct {
|
||||||
|
id string
|
||||||
|
title string
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------
|
||||||
|
// YOUTUBE SERVICE
|
||||||
|
// ---------------
|
||||||
|
|
||||||
|
// Name of the service
|
||||||
|
func (yt YouTube) ServiceName() string {
|
||||||
|
return "Youtube"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks to see if service will accept URL
|
||||||
|
func (yt YouTube) URLRegex(url string) bool {
|
||||||
|
return RegexpFromURL(url, append(youtubeVideoPatterns, []string{youtubePlaylistPattern}...)) != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates the requested song/playlist and adds to the queue
|
||||||
|
func (yt YouTube) NewRequest(user *gumble.User, url string) (string, error) {
|
||||||
|
var shortURL, startOffset = "", ""
|
||||||
|
if re, err := regexp.Compile(youtubePlaylistPattern); err == nil {
|
||||||
|
if re.MatchString(url) {
|
||||||
|
if dj.HasPermission(user.Name, dj.conf.Permissions.AdminAddPlaylists) {
|
||||||
|
shortURL = re.FindStringSubmatch(url)[1]
|
||||||
|
playlist, err := yt.NewPlaylist(user.Name, shortURL)
|
||||||
|
return playlist.Title(), err
|
||||||
|
} else {
|
||||||
|
return "", errors.New("NO_PLAYLIST_PERMISSION")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
re = RegexpFromURL(url, youtubeVideoPatterns)
|
||||||
|
matches := re.FindAllStringSubmatch(url, -1)
|
||||||
|
shortURL = matches[0][1]
|
||||||
|
if len(matches[0]) == 3 {
|
||||||
|
startOffset = matches[0][2]
|
||||||
|
}
|
||||||
|
song, err := yt.NewSong(user.Name, shortURL, startOffset, nil)
|
||||||
|
return song.Title(), err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSong gathers the metadata for a song extracted from a YouTube video, and returns
|
||||||
// the song.
|
// the song.
|
||||||
func NewYouTubeSong(user, id, offset string, playlist *YouTubePlaylist) (*YouTubeSong, error) {
|
func (yt YouTube) NewSong(user, id, offset string, playlist *YouTubePlaylist) (*YouTubeSong, error) {
|
||||||
var apiResponse *jsonq.JsonQuery
|
var apiResponse *jsonq.JsonQuery
|
||||||
var err error
|
var err error
|
||||||
url := fmt.Sprintf("https://www.googleapis.com/youtube/v3/videos?part=snippet,contentDetails&id=%s&key=%s",
|
url := fmt.Sprintf("https://www.googleapis.com/youtube/v3/videos?part=snippet,contentDetails&id=%s&key=%s",
|
||||||
id, os.Getenv("YOUTUBE_API_KEY"))
|
id, os.Getenv("YOUTUBE_API_KEY"))
|
||||||
if apiResponse, err = PerformGetRequest(url); err != nil {
|
if apiResponse, err = yt.PerformGetRequest(url); err != nil {
|
||||||
return nil, errors.New(INVALID_API_KEY)
|
return nil, errors.New(INVALID_API_KEY)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,6 +199,46 @@ func NewYouTubeSong(user, id, offset string, playlist *YouTubePlaylist) (*YouTub
|
||||||
return nil, errors.New(VIDEO_TOO_LONG_MSG)
|
return nil, errors.New(VIDEO_TOO_LONG_MSG)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewPlaylist gathers the metadata for a YouTube playlist and returns it.
|
||||||
|
func (yt YouTube) NewPlaylist(user, id string) (*YouTubePlaylist, error) {
|
||||||
|
var apiResponse *jsonq.JsonQuery
|
||||||
|
var err error
|
||||||
|
// Retrieve title of playlist
|
||||||
|
url := fmt.Sprintf("https://www.googleapis.com/youtube/v3/playlists?part=snippet&id=%s&key=%s",
|
||||||
|
id, os.Getenv("YOUTUBE_API_KEY"))
|
||||||
|
if apiResponse, err = yt.PerformGetRequest(url); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
title, _ := apiResponse.String("items", "0", "snippet", "title")
|
||||||
|
|
||||||
|
playlist := &YouTubePlaylist{
|
||||||
|
id: id,
|
||||||
|
title: title,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve items in playlist
|
||||||
|
url = fmt.Sprintf("https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=50&playlistId=%s&key=%s",
|
||||||
|
id, os.Getenv("YOUTUBE_API_KEY"))
|
||||||
|
if apiResponse, err = yt.PerformGetRequest(url); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
numVideos, _ := apiResponse.Int("pageInfo", "totalResults")
|
||||||
|
if numVideos > 50 {
|
||||||
|
numVideos = 50
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < numVideos; i++ {
|
||||||
|
index := strconv.Itoa(i)
|
||||||
|
videoID, _ := apiResponse.String("items", index, "snippet", "resourceId", "videoId")
|
||||||
|
yt.NewSong(user, videoID, "", playlist)
|
||||||
|
}
|
||||||
|
return playlist, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------
|
||||||
|
// YOUTUBE SONG
|
||||||
|
// ------------
|
||||||
|
|
||||||
// Download downloads the song via youtube-dl if it does not already exist on disk.
|
// Download downloads the song via youtube-dl if it does not already exist on disk.
|
||||||
// All downloaded songs are stored in ~/.mumbledj/songs and should be automatically cleaned.
|
// All downloaded songs are stored in ~/.mumbledj/songs and should be automatically cleaned.
|
||||||
func (s *YouTubeSong) Download() error {
|
func (s *YouTubeSong) Download() error {
|
||||||
|
@ -380,48 +416,6 @@ func (s *YouTubeSong) SetDontSkip(value bool) {
|
||||||
// YOUTUBE PLAYLIST
|
// YOUTUBE PLAYLIST
|
||||||
// ----------------
|
// ----------------
|
||||||
|
|
||||||
// YouTubePlaylist holds the metadata for a YouTube playlist.
|
|
||||||
type YouTubePlaylist struct {
|
|
||||||
id string
|
|
||||||
title string
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewYouTubePlaylist gathers the metadata for a YouTube playlist and returns it.
|
|
||||||
func NewYouTubePlaylist(user, id string) (*YouTubePlaylist, error) {
|
|
||||||
var apiResponse *jsonq.JsonQuery
|
|
||||||
var err error
|
|
||||||
// Retrieve title of playlist
|
|
||||||
url := fmt.Sprintf("https://www.googleapis.com/youtube/v3/playlists?part=snippet&id=%s&key=%s",
|
|
||||||
id, os.Getenv("YOUTUBE_API_KEY"))
|
|
||||||
if apiResponse, err = PerformGetRequest(url); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
title, _ := apiResponse.String("items", "0", "snippet", "title")
|
|
||||||
|
|
||||||
playlist := &YouTubePlaylist{
|
|
||||||
id: id,
|
|
||||||
title: title,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieve items in playlist
|
|
||||||
url = fmt.Sprintf("https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=50&playlistId=%s&key=%s",
|
|
||||||
id, os.Getenv("YOUTUBE_API_KEY"))
|
|
||||||
if apiResponse, err = PerformGetRequest(url); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
numVideos, _ := apiResponse.Int("pageInfo", "totalResults")
|
|
||||||
if numVideos > 50 {
|
|
||||||
numVideos = 50
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < numVideos; i++ {
|
|
||||||
index := strconv.Itoa(i)
|
|
||||||
videoID, _ := apiResponse.String("items", index, "snippet", "resourceId", "videoId")
|
|
||||||
NewYouTubeSong(user, videoID, "", playlist)
|
|
||||||
}
|
|
||||||
return playlist, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddSkip adds a skip to the playlist's skippers slice.
|
// AddSkip adds a skip to the playlist's skippers slice.
|
||||||
func (p *YouTubePlaylist) AddSkip(username string) error {
|
func (p *YouTubePlaylist) AddSkip(username string) error {
|
||||||
for _, user := range dj.playlistSkips[p.ID()] {
|
for _, user := range dj.playlistSkips[p.ID()] {
|
||||||
|
@ -475,7 +469,7 @@ func (p *YouTubePlaylist) Title() string {
|
||||||
// -----------
|
// -----------
|
||||||
|
|
||||||
// PerformGetRequest does all the grunt work for a YouTube HTTPS GET request.
|
// PerformGetRequest does all the grunt work for a YouTube HTTPS GET request.
|
||||||
func PerformGetRequest(url string) (*jsonq.JsonQuery, error) {
|
func (yt YouTube) PerformGetRequest(url string) (*jsonq.JsonQuery, error) {
|
||||||
jsonString := ""
|
jsonString := ""
|
||||||
|
|
||||||
if response, err := http.Get(url); err == nil {
|
if response, err := http.Get(url); err == nil {
|
||||||
|
|
61
web.go
61
web.go
|
@ -12,37 +12,70 @@ import (
|
||||||
"github.com/layeh/gumble/gumble"
|
"github.com/layeh/gumble/gumble"
|
||||||
)
|
)
|
||||||
|
|
||||||
var client_token = make(map[*gumble.User]string)
|
type WebServer struct {
|
||||||
var token_client = make(map[string]*gumble.User)
|
port int
|
||||||
var external_ip = ""
|
client_token map[*gumble.User]string
|
||||||
|
token_client map[string]*gumble.User
|
||||||
func Webserver() {
|
|
||||||
http.HandleFunc("/", homepage)
|
|
||||||
http.HandleFunc("/add", addSong)
|
|
||||||
http.ListenAndServe(":9563", nil)
|
|
||||||
rand.Seed(time.Now().UnixNano())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func homepage(w http.ResponseWriter, r *http.Request) {
|
type Page struct {
|
||||||
|
siteUrl string
|
||||||
|
token string
|
||||||
|
}
|
||||||
|
|
||||||
|
var external_ip = ""
|
||||||
|
|
||||||
|
func Webserver(port int) *WebServer {
|
||||||
|
var webserver = WebServer{port, make(map[*gumble.User]string), make(map[string]*gumble.User)}
|
||||||
|
http.HandleFunc("/", webServer.homepage)
|
||||||
|
http.HandleFunc("/add", webserver.add)
|
||||||
|
http.HandleFunc("/volume", webserver.volume)
|
||||||
|
http.HandleFunc("/skip", webserver.skip)
|
||||||
|
http.ListenAndServe(":"+port, nil)
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
return &webserver
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w WebServer) homepage(w http.ResponseWriter, r *http.Request) {
|
||||||
var uname = token_client[r.URL.Path[1:]]
|
var uname = token_client[r.URL.Path[1:]]
|
||||||
if uname == nil {
|
if uname == nil {
|
||||||
fmt.Fprintf(w, "Invalid Token")
|
fmt.Fprintf(w, "Invalid Token")
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprintf(w, "Hang in there %s, I haven't made the website yet!", uname.Name)
|
t, _ := template.ParseFiles("index.html")
|
||||||
|
t.Execute(w, Page{"http://" + getIp() + ":" + w.port + "/", r.URL.Path[1:]})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func addSong(w http.ResponseWriter, r *http.Request) {
|
func (w WebServer) add(w http.ResponseWriter, r *http.Request) {
|
||||||
var uname = token_client[r.FormValue("token")]
|
var uname = token_client[r.FormValue("token")]
|
||||||
if uname == nil {
|
if uname == nil {
|
||||||
fmt.Fprintf(w, "Invalid Token")
|
fmt.Fprintf(w, "Invalid Token")
|
||||||
} else {
|
} else {
|
||||||
var url = html.UnescapeString(r.FormValue("url"))
|
add(uname, html.UnescapeString(r.FormValue("value")))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w WebServer) volume(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var uname = token_client[r.FormValue("token")]
|
||||||
|
if uname == nil {
|
||||||
|
fmt.Fprintf(w, "Invalid Token")
|
||||||
|
} else {
|
||||||
|
var url = html.UnescapeString(r.FormValue("value"))
|
||||||
add(uname, url)
|
add(uname, url)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetWebAddress(user *gumble.User) {
|
func (w WebServer) skip(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var uname = token_client[r.FormValue("token")]
|
||||||
|
if uname == nil {
|
||||||
|
fmt.Fprintf(w, "Invalid Token")
|
||||||
|
} else {
|
||||||
|
var url = html.UnescapeString(r.FormValue("value"))
|
||||||
|
add(uname, url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w WebServer) GetWebAddress(user *gumble.User) {
|
||||||
if client_token[user] != "" {
|
if client_token[user] != "" {
|
||||||
token_client[client_token[user]] = nil
|
token_client[client_token[user]] = nil
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue