mirror of
https://github.com/aunefyren/wrapperr
synced 2024-11-10 13:44:12 +00:00
Ignore users
Admin panel css tweaks
This commit is contained in:
parent
eaab43f8e9
commit
74db0ebd7b
9 changed files with 190 additions and 9 deletions
1
main.go
1
main.go
|
@ -171,6 +171,7 @@ func initRouter(config models.WrapperrConfig) *gin.Engine {
|
|||
admin.POST("/get/cache-statistics", routes.ApiWrapperCacheStatistics)
|
||||
admin.POST("/get/users", routes.ApiGetUsers)
|
||||
admin.POST("/get/users/:userId", routes.ApiGetUser)
|
||||
admin.POST("/get/users/:userId/ignore", routes.ApiIgnoreUser)
|
||||
admin.POST("/sync/users", routes.ApiSyncTautulliUsers)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,3 +10,7 @@ type AdminConfigUpdateRequest struct {
|
|||
AdminPassword string `json:"admin_password"`
|
||||
AdminPasswordOriginal string `json:"admin_password_original"`
|
||||
}
|
||||
|
||||
type AdminIgnoreUser struct {
|
||||
Ignore bool `json:"user_ignore"`
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ type WrapperrUser struct {
|
|||
Active bool `json:"user_active"`
|
||||
TautulliServers []string `json:"user_tautulli_servers"`
|
||||
Wrappings []WrapperrHistoryEntry `json:"wrappings"`
|
||||
Ignore bool `json:"user_ignore"`
|
||||
}
|
||||
|
||||
type WrapperrHistoryEntry struct {
|
||||
|
|
|
@ -84,6 +84,12 @@ func WrapperrDownloadDays(ID int, wrapperr_data []models.WrapperrDay, loop_inter
|
|||
var found_date bool = false
|
||||
var found_date_index int = 0
|
||||
|
||||
ignoredUserIDSArray, err := UsersGetIgnoredUserIDs()
|
||||
if err != nil {
|
||||
log.Println("Failed to get ignored users. Error: " + err.Error())
|
||||
return []models.WrapperrDay{}, false, errors.New("Failed to get ignored users.")
|
||||
}
|
||||
|
||||
// If loop_interval is less than one, do not utilize the loop interval and set use_loop_interval to false
|
||||
if loop_interval < 1 {
|
||||
use_loop_interval = false
|
||||
|
@ -216,6 +222,18 @@ func WrapperrDownloadDays(ID int, wrapperr_data []models.WrapperrDay, loop_inter
|
|||
for j := 0; j < len(tautulli_data); j++ {
|
||||
if tautulli_data[j].MediaType == "movie" || tautulli_data[j].MediaType == "episode" || tautulli_data[j].MediaType == "track" {
|
||||
|
||||
// If the data is generated by an ignored user, skip the data
|
||||
ignoreData := false
|
||||
for u := 0; u < len(ignoredUserIDSArray); u++ {
|
||||
if ignoredUserIDSArray[u] == tautulli_data[j].UserID {
|
||||
ignoreData = true
|
||||
}
|
||||
}
|
||||
if ignoreData {
|
||||
continue
|
||||
}
|
||||
|
||||
// Translate data to own struct
|
||||
tautulli_entry := models.TautulliEntry{
|
||||
Date: tautulli_data[j].Date,
|
||||
RowID: tautulli_data[j].RowID,
|
||||
|
|
|
@ -267,6 +267,12 @@ func TautulliSyncUsersToWrapperr() (err error) {
|
|||
// Create Wrapperr user objects array to fill
|
||||
newUserArray := []models.WrapperrUser{}
|
||||
|
||||
ignoredUsersIDArray, err := UsersGetIgnoredUserIDs()
|
||||
if err != nil {
|
||||
log.Println("Failed to get ignored users. Error: " + err.Error())
|
||||
return errors.New("Failed to get ignored users.")
|
||||
}
|
||||
|
||||
// Create new Wrapperr user objects from Tautulli reply
|
||||
for _, userGroup := range users {
|
||||
var userMatch bool = false
|
||||
|
@ -293,6 +299,14 @@ func TautulliSyncUsersToWrapperr() (err error) {
|
|||
return errors.New("Failed to convert integer to bool.")
|
||||
}
|
||||
|
||||
var userAlreadyIgnored = false
|
||||
for _, ignoredID := range ignoredUsersIDArray {
|
||||
if ignoredID == userGroup.TautulliUser.UserID {
|
||||
userAlreadyIgnored = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Create new object
|
||||
wrapperrUser := models.WrapperrUser{
|
||||
FriendlyName: userGroup.TautulliUser.FriendlyName,
|
||||
|
@ -302,6 +316,7 @@ func TautulliSyncUsersToWrapperr() (err error) {
|
|||
TautulliServers: []string{userGroup.TautulliServer},
|
||||
Active: Active,
|
||||
Wrappings: []models.WrapperrHistoryEntry{},
|
||||
Ignore: userAlreadyIgnored,
|
||||
}
|
||||
|
||||
// Push to array
|
||||
|
@ -327,7 +342,7 @@ func TautulliSyncUsersToWrapperr() (err error) {
|
|||
return errors.New("Failed to save new user.")
|
||||
}
|
||||
} else {
|
||||
err = UsersUpdateUser(user.UserID, user.FriendlyName, user.User, user.Email, user.Active, user.TautulliServers)
|
||||
err = UsersUpdateUser(user.UserID, user.FriendlyName, user.User, user.Email, user.Active, user.TautulliServers, user.Ignore)
|
||||
if err != nil {
|
||||
log.Println("Failed to update user. Error: " + err.Error())
|
||||
return errors.New("Failed to update user.")
|
||||
|
|
|
@ -59,7 +59,7 @@ func UsersGetUser(userID int) (user models.WrapperrUser, err error) {
|
|||
return user, errors.New("User not found.")
|
||||
}
|
||||
|
||||
func UsersUpdateUser(userID int, FriendlyName string, userName string, Email string, Active bool, TautulliServers []string) (err error) {
|
||||
func UsersUpdateUser(userID int, FriendlyName string, userName string, Email string, Active bool, TautulliServers []string, Ignore bool) (err error) {
|
||||
err = nil
|
||||
|
||||
users, err := files.GetUsers()
|
||||
|
@ -86,6 +86,7 @@ func UsersUpdateUser(userID int, FriendlyName string, userName string, Email str
|
|||
users[userIndex].FriendlyName = FriendlyName
|
||||
users[userIndex].User = userName
|
||||
users[userIndex].TautulliServers = TautulliServers
|
||||
users[userIndex].Ignore = Ignore
|
||||
|
||||
err = files.SaveUsers(users)
|
||||
if err != nil {
|
||||
|
@ -95,3 +96,22 @@ func UsersUpdateUser(userID int, FriendlyName string, userName string, Email str
|
|||
|
||||
return
|
||||
}
|
||||
|
||||
func UsersGetIgnoredUserIDs() (users []int, err error) {
|
||||
err = nil
|
||||
users = []int{}
|
||||
|
||||
foundUsers, err := files.GetUsers()
|
||||
if err != nil {
|
||||
log.Println("Failed to get users. Error: " + err.Error())
|
||||
return users, errors.New("Failed to get users.")
|
||||
}
|
||||
|
||||
for _, foundUser := range foundUsers {
|
||||
if foundUser.Ignore {
|
||||
users = append(users, foundUser.UserID)
|
||||
}
|
||||
}
|
||||
|
||||
return users, err
|
||||
}
|
||||
|
|
|
@ -452,3 +452,65 @@ func ApiSyncTautulliUsers(context *gin.Context) {
|
|||
context.JSON(http.StatusOK, gin.H{"message": "Users synced.", "data": newusers})
|
||||
return
|
||||
}
|
||||
|
||||
func ApiIgnoreUser(context *gin.Context) {
|
||||
configBool, err := files.GetConfigState()
|
||||
if err != nil {
|
||||
log.Println("Failed to retrieve configuration state. Error: " + err.Error())
|
||||
context.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to retrieve configuration state."})
|
||||
context.Abort()
|
||||
return
|
||||
} else if !configBool {
|
||||
context.JSON(http.StatusBadRequest, gin.H{"error": "Wrapperr is not configured."})
|
||||
context.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
var userId = context.Param("userId")
|
||||
|
||||
userIDInt, err := strconv.Atoi(userId)
|
||||
if err != nil {
|
||||
log.Println("Failed to parse user ID. Error: " + err.Error())
|
||||
context.JSON(http.StatusBadRequest, gin.H{"error": "Failed to parse user ID."})
|
||||
context.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
// Read payload from Post input
|
||||
var ignorePayload models.AdminIgnoreUser
|
||||
if err := context.ShouldBindJSON(&ignorePayload); err != nil {
|
||||
log.Println("Failed to parse request. Error: " + err.Error())
|
||||
context.JSON(http.StatusBadRequest, gin.H{"error": "Failed to parse request."})
|
||||
context.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
user, err := modules.UsersGetUser(userIDInt)
|
||||
if err != nil {
|
||||
log.Println("Failed to get user. Error: " + err.Error())
|
||||
context.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get user."})
|
||||
context.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
user.Ignore = ignorePayload.Ignore
|
||||
|
||||
err = modules.UsersUpdateUser(user.UserID, user.FriendlyName, user.User, user.Email, user.Active, user.TautulliServers, user.Ignore)
|
||||
if err != nil {
|
||||
log.Println("Failed to update user. Error: " + err.Error())
|
||||
context.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update user."})
|
||||
context.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
err = files.ClearCache()
|
||||
if err != nil {
|
||||
log.Println("Failed to clear cache. Error: " + err.Error())
|
||||
context.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to clear cache."})
|
||||
context.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
context.JSON(http.StatusOK, gin.H{"message": "User toggeled."})
|
||||
return
|
||||
}
|
||||
|
|
|
@ -329,6 +329,7 @@ a {
|
|||
background-color: var(--charcoal);
|
||||
color: var(--white);
|
||||
border-radius: 0.25em;
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
.user-object {
|
||||
|
@ -344,11 +345,22 @@ a {
|
|||
align-items: center;
|
||||
}
|
||||
|
||||
.user-userid, .user-active {
|
||||
.user-userid, .user-active, .user-ignore, .user-logbutton {
|
||||
margin: 0.25em 0.5em;
|
||||
text-align: center;
|
||||
width: 5em;
|
||||
overflow: hidden;
|
||||
height: 2em;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.user-logbutton {
|
||||
height: 3em;
|
||||
}
|
||||
|
||||
.user-active-true {
|
||||
|
@ -440,10 +452,6 @@ a {
|
|||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.user-logbutton {
|
||||
width: 4em;
|
||||
}
|
||||
|
||||
/* The Modal (background) */
|
||||
.modal {
|
||||
display: none; /* Hidden by default */
|
||||
|
|
|
@ -74,6 +74,8 @@ function placeUsers(usersArray) {
|
|||
<div class="user-header">Email</div>
|
||||
<div class="user-header-short">Active</div>
|
||||
<div class="user-header">Tautulli servers</div>
|
||||
<div class="user-header-short">Ignore user</div>
|
||||
<div class="user-header-short">History</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
|
@ -85,6 +87,11 @@ function placeUsers(usersArray) {
|
|||
<button class="form-control btn" name="historyButton" id="historyButton" onclick="getHistory(${user.user_id});" style="width: 2em; height: 2em; padding: 0.25em;"><img src="${root}/assets/document.svg" class="btn_solo"></img><p2 id="historyButtonImage"></p2></button>
|
||||
</div>
|
||||
`;
|
||||
} else {
|
||||
historyDiv = `
|
||||
<div class="user-logbutton">
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
var active_state_class = ""
|
||||
|
@ -99,6 +106,11 @@ function placeUsers(usersArray) {
|
|||
tautulliServersString += `<div class="tautulli-server-badge" title="${server}">${server}</div>`
|
||||
});
|
||||
|
||||
var ignoredUserString = ""
|
||||
if(user.user_ignore) {
|
||||
ignoredUserString = "checked"
|
||||
}
|
||||
|
||||
var html = `
|
||||
<div class="user-object">
|
||||
<div class="user-details">
|
||||
|
@ -112,10 +124,12 @@ function placeUsers(usersArray) {
|
|||
</div>
|
||||
</div>
|
||||
<div class="user-tautulli-servers">${tautulliServersString}</div>
|
||||
<div class="user-ignore">
|
||||
<input style="margin: auto;" class="clickable" type="checkbox" id="ignore_user_check_${user.user_id}" name="ignore_user_check_${user.user_id}" onclick="toggleUserIgnore('${user.user_id}', ${user.user_ignore})" value="" ${ignoredUserString}>
|
||||
</div>
|
||||
|
||||
${historyDiv}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
userModule.innerHTML += html;
|
||||
|
@ -204,3 +218,41 @@ function syncTautulli() {
|
|||
xhttp.send();
|
||||
return;
|
||||
}
|
||||
|
||||
function toggleUserIgnore(userId, currentIgnoreValue) {
|
||||
if(!confirm("Are you sure? The cache will be deleted for it to take effect.")) {
|
||||
return;
|
||||
}
|
||||
|
||||
var ignoreValue = !currentIgnoreValue
|
||||
data_form = {
|
||||
"user_ignore": ignoreValue
|
||||
};
|
||||
|
||||
var data_obj = JSON.stringify(data_form);
|
||||
|
||||
var xhttp = new XMLHttpRequest();
|
||||
xhttp.onreadystatechange = function() {
|
||||
if (this.readyState == 4) {
|
||||
try {
|
||||
var result= JSON.parse(this.responseText);
|
||||
} catch(error) {
|
||||
alert('Failed to parse API response.');
|
||||
console.log('Failed to parse API response. Error: ' + this.responseText);
|
||||
return;
|
||||
}
|
||||
|
||||
if(result.error) {
|
||||
document.getElementById("ignore_user_check_" + userId).checked = currentIgnoreValue;
|
||||
alert(result.error);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
xhttp.withCredentials = true;
|
||||
xhttp.open("post", api_url + "get/users/" + userId + "/ignore");
|
||||
xhttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
|
||||
xhttp.setRequestHeader("Authorization", cookie);
|
||||
xhttp.send(data_obj);
|
||||
return;
|
||||
}
|
Loading…
Reference in a new issue