diff --git a/config/config.go b/config/config.go index 4204a2c..98df821 100644 --- a/config/config.go +++ b/config/config.go @@ -7,6 +7,7 @@ import ( "github.com/BurntSushi/toml" ) +// Config defines config fields type Config struct { DatabaseConnection string BindAddress string @@ -20,14 +21,17 @@ type Config struct { Folder Folder } +// Folder defines fields for Folder configuration type Folder struct { Folder string } +// Instagram defines fields for Instagram configuration type Instagram struct { Tag string } +// Twitter defines fields for Twitter configuration type Twitter struct { ConsumerKey string ConsumerSecret string @@ -36,8 +40,9 @@ type Twitter struct { Filter []string } +// Snapchat defines fields for Snapchat configuration type Snapchat struct { - ApiBase string + APIBase string UserAgent string UserName string GetConversations SnapchatEndpoint @@ -45,19 +50,24 @@ type Snapchat struct { MarkAsSeen SnapchatEndpoint } +// SnapchatEndpoint defines fields for Snapchat endpoint configuration type SnapchatEndpoint struct { - Uuid string + UUID string ClientAuthToken string RequestToken string Timestamp string } +// C is the config handler var C Config +// LoadConfig loads the configuration from given path func LoadConfig(path string) error { _, e := toml.DecodeFile(path, &C) return e } + +// WriteConfig writes the configuration to the given path func WriteConfig(path string) error { buf := new(bytes.Buffer) err := toml.NewEncoder(buf).Encode(C) diff --git a/database/main.go b/database/main.go index d2796d5..79b8ad7 100644 --- a/database/main.go +++ b/database/main.go @@ -7,11 +7,13 @@ import ( "git.1750studios.com/AniNite/SocialDragon/config" "github.com/jinzhu/gorm" - _ "github.com/lib/pq" + _ "github.com/lib/pq" // Database backend for GORM ) +// Service defines the service providers type Service uint +// IDs for the service providers const ( Snapchat Service = iota Twitter @@ -19,16 +21,19 @@ const ( Folder ) +// State defines the states a media item can have type State uint +// Possible states const ( Inbox State = iota Approved Rejected ) -type updatecallback func(Item) +type updateCallbackT func(Item) +// Item defines the databse model type Item struct { ID uint `gorm:"primary_key"` CreatedAt time.Time @@ -43,6 +48,7 @@ type Item struct { OriginalID string } +// User defines the database model type User struct { ID uint `gorm:"primary_key"` CreatedAt time.Time @@ -55,10 +61,12 @@ type User struct { Blocked bool } +// Db is the database handler var Db *gorm.DB -var cb updatecallback +var cb updateCallbackT -func InitDb(callback updatecallback) { +// InitDb opens and sets up database +func InitDb(callback updateCallbackT) { cb = callback var err error Db, err = gorm.Open("postgres", config.C.DatabaseConnection) @@ -71,6 +79,7 @@ func InitDb(callback updatecallback) { Db.AutoMigrate(&Item{}, &User{}) } +// AfterSave sends updates over the callback func (IT *Item) AfterSave(scope *gorm.Scope) (err error) { go cb(*IT) return diff --git a/folder/main.go b/folder/main.go index 362679b..3596ba2 100644 --- a/folder/main.go +++ b/folder/main.go @@ -15,6 +15,7 @@ import ( "git.1750studios.com/AniNite/SocialDragon/database" ) +// LoadNewFolders loads the content of configured folder to database func LoadNewFolders() { log.Printf("Loading new folders...") files, _ := ioutil.ReadDir(config.C.Folder.Folder) @@ -45,6 +46,7 @@ func LoadNewFolders() { } } +// ImageNameGenerator generates media paths func ImageNameGenerator(seed string) (string, string) { seedBytes := []byte(seed) sha256Bytes := sha256.Sum256(seedBytes) @@ -56,6 +58,6 @@ func ImageNameGenerator(seed string) (string, string) { } ext := strings.Split(seed, ".") finalPath := folders + hash + "." + ext[len(ext)-1] - finalUrl := urls + hash + "." + ext[len(ext)-1] - return finalPath, finalUrl + finalURL := urls + hash + "." + ext[len(ext)-1] + return finalPath, finalURL } diff --git a/instagram/api.go b/instagram/api.go index ef59798..fc17620 100644 --- a/instagram/api.go +++ b/instagram/api.go @@ -15,7 +15,8 @@ import ( "git.1750studios.com/AniNite/SocialDragon/config" ) -type InstagramListResponse struct { +// ListResponse defines the instagram list response +type ListResponse struct { Tag struct { Name string `json:"name"` ContentAdvisory interface{} `json:"content_advisory"` @@ -76,7 +77,8 @@ type InstagramListResponse struct { } `json:"tag"` } -type InstagramPostResponse struct { +// PostResponse defines the instagram post response +type PostResponse struct { Graphql struct { ShortcodeMedia struct { Typename string `json:"__typename"` @@ -157,8 +159,9 @@ type InstagramPostResponse struct { } `json:"graphql"` } -func LoadList(token string) (*InstagramListResponse, error) { - var listResponse InstagramListResponse +// LoadList loads the media list of a instagram page +func LoadList(token string) (*ListResponse, error) { + var listResponse ListResponse var url string if token == "" { url = "https://www.instagram.com/explore/tags/" + config.C.Instagram.Tag + "/?__a=1" @@ -181,8 +184,9 @@ func LoadList(token string) (*InstagramListResponse, error) { return &listResponse, nil } -func LoadPost(code string) (*InstagramPostResponse, error) { - var postResponse InstagramPostResponse +// LoadPost loads single post from instagram +func LoadPost(code string) (*PostResponse, error) { + var postResponse PostResponse res, err := GetHTTPResource("https://www.instagram.com/p/" + code + "/?__a=1") if err != nil { return nil, err @@ -199,6 +203,7 @@ func LoadPost(code string) (*InstagramPostResponse, error) { return &postResponse, nil } +// ImageNameGenerator generates media paths func ImageNameGenerator(seed string) (string, string) { seedBytes := []byte(seed) sha256Bytes := sha256.Sum256(seedBytes) @@ -209,10 +214,11 @@ func ImageNameGenerator(seed string) (string, string) { log.Fatalf("FAT Could not create ContentDirectory, error: %+v", err) } finalPath := folders + hash - finalUrl := urls + hash - return finalPath, finalUrl + finalURL := urls + hash + return finalPath, finalURL } +// DownloadMedia downloads given media from Instagram func DownloadMedia(data io.Reader, path string, video bool) (string, error) { if video { ext := ".mp4" @@ -228,16 +234,15 @@ func DownloadMedia(data io.Reader, path string, video bool) (string, error) { return "", err } return ext, nil - } else { - ext := ".jpg" - image, err := imaging.Decode(data) - if err != nil { - return "", err - } - err = imaging.Save(image, path+ext) - if err != nil { - return "", err - } - return ext, nil } + ext := ".jpg" + image, err := imaging.Decode(data) + if err != nil { + return "", err + } + err = imaging.Save(image, path+ext) + if err != nil { + return "", err + } + return ext, nil } diff --git a/instagram/http.go b/instagram/http.go index 148d437..961d6ac 100644 --- a/instagram/http.go +++ b/instagram/http.go @@ -10,6 +10,7 @@ import ( var sem = make(chan byte, 2) var client = &http.Client{} +// GetHTTPResource gets HTTP resource with Instagram headers func GetHTTPResource(u string) (*http.Response, error) { sem <- 1 req, err := http.NewRequest("GET", u, nil) diff --git a/instagram/main.go b/instagram/main.go index 6ba303d..e19e2da 100644 --- a/instagram/main.go +++ b/instagram/main.go @@ -8,6 +8,7 @@ import ( var running bool +// LoadNewInstas gets new media from Instagram func LoadNewInstas() { log.Printf("Loading new Instas...") var count int @@ -32,7 +33,7 @@ func LoadNewInstas() { log.Printf("Finished looking for new Instas.") } -func iterList(list *InstagramListResponse) string { +func iterList(list *ListResponse) string { var token string for _, image := range list.Tag.Media.Nodes { var count int diff --git a/snapchat/api.go b/snapchat/api.go index 83d455a..b458a89 100644 --- a/snapchat/api.go +++ b/snapchat/api.go @@ -15,25 +15,27 @@ import ( "git.1750studios.com/AniNite/SocialDragon/config" ) -type Conversations struct { - ConversationsResponse []ConversationsResponse `json:"conversations_response"` +// ConversationsT Snapchat conversations +type ConversationsT struct { + ConversationsResponse []conversationsResponseT `json:"conversations_response"` } -type ConversationsResponse struct { - PendingReceivedSnaps []Snap `json:"pending_received_snaps"` +type conversationsResponseT struct { + PendingReceivedSnaps []snapT `json:"pending_received_snaps"` } -type Snap struct { - Id string `json:"id"` +type snapT struct { + ID string `json:"id"` Username string `json:"sn"` Movie int `json:"m"` Rotation int `json:"mo"` } -func GetConversations() (*Conversations, error) { - var conversations Conversations +// GetConversations returns a list of snapchat conversations +func GetConversations() (*ConversationsT, error) { + var conversations ConversationsT headers := map[string]string{ - "X-Snapchat-UUID": config.C.Snapchat.GetConversations.Uuid, + "X-Snapchat-UUID": config.C.Snapchat.GetConversations.UUID, "X-Snapchat-Client-Auth-Token": config.C.Snapchat.GetConversations.ClientAuthToken, } data := map[string]string{ @@ -59,13 +61,14 @@ func GetConversations() (*Conversations, error) { return &conversations, nil } -func GetBlob(snap Snap) (string, error) { +// GetBlob downloads the given snap +func GetBlob(snap snapT) (string, error) { headers := map[string]string{ - "X-Snapchat-UUID": config.C.Snapchat.GetBlob.Uuid, + "X-Snapchat-UUID": config.C.Snapchat.GetBlob.UUID, "X-Snapchat-Client-Auth-Token": config.C.Snapchat.GetBlob.ClientAuthToken, } data := map[string]string{ - "id": snap.Id, + "id": snap.ID, "req_token": config.C.Snapchat.GetBlob.RequestToken, "timestamp": config.C.Snapchat.GetBlob.Timestamp, "username": config.C.Snapchat.UserName, @@ -74,18 +77,19 @@ func GetBlob(snap Snap) (string, error) { if err != nil { return "", err } - name, uname := ImageNameGenerator(snap.Id) + name, uname := imageNameGenerator(snap.ID) defer res.Body.Close() - ext, err := RotateImage(snap, res.Body, name) + ext, err := rotateImage(snap, res.Body, name) if err != nil { return "", err } return uname + ext, nil } -func MarkAsSeen(snap Snap, screenshotted bool) error { +// MarkAsSeen marks the given snap as seen, optionally screenshotted +func MarkAsSeen(snap snapT, screenshotted bool) error { headers := map[string]string{ - "X-Snapchat-UUID": config.C.Snapchat.MarkAsSeen.Uuid, + "X-Snapchat-UUID": config.C.Snapchat.MarkAsSeen.UUID, "X-Snapchat-Client-Auth-Token": config.C.Snapchat.MarkAsSeen.ClientAuthToken, } data := map[string]string{ @@ -94,9 +98,9 @@ func MarkAsSeen(snap Snap, screenshotted bool) error { "username": config.C.Snapchat.UserName, } if screenshotted { - data["json"] = "{\"" + snap.Id + "\":{\"t\":1467469712.44128,\"replayed\":0,\"c\":1,\"stack_id\":\"E437851F-2AA8-4C6C-AE11-5FB49FBF93C0\",\"sv\":0,\"es_id\":\"cssek-0::TgcQVwLCU3kHIEj+o6s2CQ==:QTm2VyfemhN5owtHmVuMpik4hwFNz4gSpUQ9D9zlWxatYA==\"}}" + data["json"] = "{\"" + snap.ID + "\":{\"t\":1467469712.44128,\"replayed\":0,\"c\":1,\"stack_id\":\"E437851F-2AA8-4C6C-AE11-5FB49FBF93C0\",\"sv\":0,\"es_id\":\"cssek-0::TgcQVwLCU3kHIEj+o6s2CQ==:QTm2VyfemhN5owtHmVuMpik4hwFNz4gSpUQ9D9zlWxatYA==\"}}" } else { - data["json"] = "{\"" + snap.Id + "\":{\"t\":1467469712.44128,\"replayed\":0,\"stack_id\":\"E437851F-2AA8-4C6C-AE11-5FB49FBF93C0\",\"sv\":0,\"es_id\":\"cssek-0::TgcQVwLCU3kHIEj+o6s2CQ==:QTm2VyfemhN5owtHmVuMpik4hwFNz4gSpUQ9D9zlWxatYA==\"}}" + data["json"] = "{\"" + snap.ID + "\":{\"t\":1467469712.44128,\"replayed\":0,\"stack_id\":\"E437851F-2AA8-4C6C-AE11-5FB49FBF93C0\",\"sv\":0,\"es_id\":\"cssek-0::TgcQVwLCU3kHIEj+o6s2CQ==:QTm2VyfemhN5owtHmVuMpik4hwFNz4gSpUQ9D9zlWxatYA==\"}}" } res, err := GetHTTPResource("/bq/update_snaps", headers, data) if err != nil { @@ -106,7 +110,7 @@ func MarkAsSeen(snap Snap, screenshotted bool) error { return nil } -func ImageNameGenerator(seed string) (string, string) { +func imageNameGenerator(seed string) (string, string) { seedBytes := []byte(seed) sha256Bytes := sha256.Sum256(seedBytes) hash := hex.EncodeToString(sha256Bytes[:]) @@ -116,11 +120,11 @@ func ImageNameGenerator(seed string) (string, string) { log.Fatalf("FAT Could not create ContentDirectory, error: %+v", err) } finalPath := folders + hash - finalUrl := urls + hash - return finalPath, finalUrl + finalURL := urls + hash + return finalPath, finalURL } -func RotateImage(snap Snap, data io.Reader, path string) (string, error) { +func rotateImage(snap snapT, data io.Reader, path string) (string, error) { if snap.Movie != 0 { ext := ".mp4" blob, err := ioutil.ReadAll(data) @@ -135,29 +139,28 @@ func RotateImage(snap Snap, data io.Reader, path string) (string, error) { return "", err } return ext, nil - } else { - ext := ".jpg" - image, err := imaging.Decode(data) - if err != nil { - return "", err - } - switch snap.Rotation { - case 1: - image = imaging.Rotate180(image) - break - case 2: - image = imaging.Rotate90(image) - break - case 3: - image = imaging.Rotate270(image) - break - default: - break - } - err = imaging.Save(image, path+ext) - if err != nil { - return "", err - } - return ext, nil } + ext := ".jpg" + image, err := imaging.Decode(data) + if err != nil { + return "", err + } + switch snap.Rotation { + case 1: + image = imaging.Rotate180(image) + break + case 2: + image = imaging.Rotate90(image) + break + case 3: + image = imaging.Rotate270(image) + break + default: + break + } + err = imaging.Save(image, path+ext) + if err != nil { + return "", err + } + return ext, nil } diff --git a/snapchat/http.go b/snapchat/http.go index d15bc12..284ec84 100644 --- a/snapchat/http.go +++ b/snapchat/http.go @@ -14,13 +14,14 @@ import ( var sem = make(chan byte, 2) var client = &http.Client{} +// GetHTTPResource makes HTTP request with snapchat headers func GetHTTPResource(u string, headers map[string]string, data map[string]string) (*http.Response, error) { sem <- 1 form := url.Values{} for key, value := range data { form.Set(key, value) } - req, err := http.NewRequest("POST", config.C.Snapchat.ApiBase+u, strings.NewReader(form.Encode())) + req, err := http.NewRequest("POST", config.C.Snapchat.APIBase+u, strings.NewReader(form.Encode())) if err != nil { log.Fatalf("FAT HTTP - Failed to create new Request: %+v", err) <-sem diff --git a/snapchat/main.go b/snapchat/main.go index 3bceda0..5f5fe91 100644 --- a/snapchat/main.go +++ b/snapchat/main.go @@ -6,6 +6,7 @@ import ( "git.1750studios.com/AniNite/SocialDragon/database" ) +// LoadNewSnaps loads all new snaps from snapchat func LoadNewSnaps() { log.Print("Loading new Snaps...") cons, err := GetConversations() @@ -16,7 +17,7 @@ func LoadNewSnaps() { for _, con := range cons.ConversationsResponse { for _, snap := range con.PendingReceivedSnaps { var count int - if database.Db.Model(database.Item{}).Where("original_id = ?", snap.Id).Count(&count); count > 0 { + if database.Db.Model(database.Item{}).Where("original_id = ?", snap.ID).Count(&count); count > 0 { break } var US database.User @@ -27,17 +28,17 @@ func LoadNewSnaps() { US.Blocked = false database.Db.Create(&US) } - log.Printf("Found new Snap %s from %s", snap.Id, snap.Username) + log.Printf("Found new Snap %s from %s", snap.ID, snap.Username) uname, err := GetBlob(snap) if err != nil { - log.Printf("Can't load snap %s: %+v", snap.Id, err) + log.Printf("Can't load snap %s: %+v", snap.ID, err) return } - log.Printf("Loaded snap %s, location %s!", snap.Id, uname) + log.Printf("Loaded snap %s, location %s!", snap.ID, uname) var IT database.Item IT.UserID = US.ID IT.IsVideo = snap.Movie != 0 - IT.OriginalID = snap.Id + IT.OriginalID = snap.ID IT.Path = uname IT.Service = database.Snapchat if US.Blocked { @@ -48,7 +49,7 @@ func LoadNewSnaps() { database.Db.Create(&IT) err = MarkAsSeen(snap, false) if err != nil { - log.Printf("Could not mark snap %s as seen: %+v", snap.Id, err) + log.Printf("Could not mark snap %s as seen: %+v", snap.ID, err) return } } diff --git a/socialdragon/socket.go b/socialdragon/socket.go index 6a7e0df..e19da48 100644 --- a/socialdragon/socket.go +++ b/socialdragon/socket.go @@ -34,6 +34,7 @@ func wsHandler(w http.ResponseWriter, r *http.Request) { } } +// SendUpdate sends the content of IT to all connected webcosckets, gets called by database handler. func SendUpdate(IT database.Item) { for i, socket := range sockets { err := socket.WriteJSON(IT) diff --git a/socialdragon/webapp.go b/socialdragon/webapp.go index f870d82..07c7e44 100644 --- a/socialdragon/webapp.go +++ b/socialdragon/webapp.go @@ -5,7 +5,7 @@ import ( "github.com/gin-gonic/gin" ) -type Stats struct { +type statsT struct { Count struct { Items struct { Inbox uint @@ -72,7 +72,7 @@ func rejectSnap(c *gin.Context) { } func stats(c *gin.Context) { - var ST Stats + var ST statsT database.Db.Model(database.Item{}).Where("state = ?", database.Inbox).Count(&ST.Count.Items.Inbox) database.Db.Model(database.Item{}).Where("state = ?", database.Approved).Count(&ST.Count.Items.Approved) database.Db.Model(database.Item{}).Where("state = ?", database.Rejected).Count(&ST.Count.Items.Rejected) diff --git a/twitter/downloader.go b/twitter/downloader.go index 4ca5094..eea1f82 100644 --- a/twitter/downloader.go +++ b/twitter/downloader.go @@ -14,6 +14,7 @@ import ( "git.1750studios.com/AniNite/SocialDragon/config" ) +// MediaNameGenerator generates paths for media func MediaNameGenerator(seed string) (string, string) { seedBytes := []byte(seed) sha256Bytes := sha256.Sum256(seedBytes) @@ -24,10 +25,11 @@ func MediaNameGenerator(seed string) (string, string) { log.Fatalf("FAT Could not create ContentDirectory, error: %+v", err) } finalPath := folders + hash - finalUrl := urls + hash - return finalPath, finalUrl + finalURL := urls + hash + return finalPath, finalURL } +// DownloadMedia downloads media from tweet func DownloadMedia(data io.Reader, path string, video bool) (string, error) { if video { ext := ".mp4" @@ -43,16 +45,15 @@ func DownloadMedia(data io.Reader, path string, video bool) (string, error) { return "", err } return ext, nil - } else { - ext := ".jpg" - image, err := imaging.Decode(data) - if err != nil { - return "", err - } - err = imaging.Save(image, path+ext) - if err != nil { - return "", err - } - return ext, nil } + ext := ".jpg" + image, err := imaging.Decode(data) + if err != nil { + return "", err + } + err = imaging.Save(image, path+ext) + if err != nil { + return "", err + } + return ext, nil } diff --git a/twitter/http.go b/twitter/http.go index 8223155..9de0dc0 100644 --- a/twitter/http.go +++ b/twitter/http.go @@ -10,6 +10,7 @@ import ( var sem = make(chan byte, 2) var client = &http.Client{} +// GetHTTPResource makes HTTP request func GetHTTPResource(u string) (*http.Response, error) { sem <- 1 req, err := http.NewRequest("GET", u, nil) diff --git a/twitter/main.go b/twitter/main.go index 6452ead..546a43f 100644 --- a/twitter/main.go +++ b/twitter/main.go @@ -11,6 +11,7 @@ import ( var stream *twitter.Stream +// LoadNewTweets loads new tweets. Endless loop! func LoadNewTweets() error { log.Printf("Loading new tweets...") conf := oauth1.NewConfig(config.C.Twitter.ConsumerKey, config.C.Twitter.ConsumerSecret) @@ -113,6 +114,7 @@ func LoadNewTweets() error { return nil } +// Stop stops the LoadNewTweets endless loop func Stop() { log.Printf("Stopping twitter stream...") stream.Stop()