Was going to version doc, but never did and don't want to anymore.. doc site will only support latest version of watcharr.
If anyone needs an older version for any reason, can always browse through them in specific git tag.
* FaceMenu: Add about modal
added modal with about info to FaceMenu bottom.
added 4 new SVG icons.
* FaceMenu: npm format
* FaceMenu: refactor about modal
- moved about modal into its own file
- minor fixes
* AboutModal: Add text to gh/site links, use Modal title prop, add attribution file link
, added a hover effect to all links in the modal and removed the margin on h5.
Also updated the top paragraph.
* AboutModal: Remove unused style
* Menu: Use color variables
---------
Co-authored-by: IRHM <37304121+IRHM@users.noreply.github.com>
* feat: improved overall look of the series season sidebar
* SeasonsList: Responsivity fixes
- Fix responsivity for seasons when names are very long (eg on shows that have custom season names)
- Increase status icon size
- Create color variables for season episodes text for resuability and to fix bug causing z index rendering issues with opacity usage.
* SeasonsList: checkSeasonStatus: Improve log
* SeasonsList: Remove $inspect: Causing errors in console for some reason
* vars: Fix --text-color-accent for dark theme
---------
Co-authored-by: IRHM <37304121+IRHM@users.noreply.github.com>
* app layout: Fix search styling and other small issues
- return destroy func in onMount to remove event listeners
- Fix timeout var type
* search: Fix searchUsers call not waiting for debounce
Fixes issue with new `prepare` script that we added for sveltekit, would always error here since we don't have any dev dependencies in this step for the command to work.
Also made the comments for each section bigger for readability (makes it easier to scan for where sections are).
Created a new <Menu> component which is now used for all of our menus (the ones for the nav + the menu in AddToTagButton).
Looks better now, easier to use, not sure why I ever did the global style for it, that was dumb. oh wait no im smart, it was probably because it wasn't used for the complex stuff it is now anyways shulda refactored ages agU
So that we can use the setters for saving properties to localStorage after an update. $effect is not meant to be used for this, so using setters seemed like the best option, gives us a lot more control over behaviour.
This change caused an issue where the poster mouseLeave event would not fire if the poster element was moved as a result of the re-sort, so some stuff has been restructured and a new call added to check if mouse is no longer over the poster to manually unactivate it.
this was wow many time wasted trying to figure this out but at least its a one time waste i hoppe.
Removed the games filter auto removal thing in filt() because it's not _really_ necessary. We have added additional UX stuff around this since, so if this rare case ever does occur, the user has easy ways around it.
- Refactored the newest/oldest sorts into one function used for both: newestOldestSort()
- Fixed an issue in the sort where an infinite loop could be caused when A & B both have no release date (added new case to resolve this).
Now using query parameters for the search queries (q).
Don't think theres a way to get slashes (/) working in the url without putting the whole query in a query param rather than the path param.
Think this is proper REST too prob
encountered a bug where doing a search while last was loading could infinitely keep loading next pages because curPage got higher than maxContentPage.
Corrected the logic to check for curPage bigger OR equal to max page, rather than only checking equal.
* person: show message when no credits to show
also hides filters when no credits, since they don't do anything in that case.
* person: remove unused css selector
- Removed min-width so improve responsivity for mobile (overflows).
- Removed unused styles (margin-top/bottom that were overridden in .container).
- Add max-width to match PosterList.
- Remove .container and add styles to .filters (combined them).
- Now makes the out file after the request, that way we ensure the request succeeds before creating the file.
- Added logging to every case, should make debugging easier in the future.
* Poster: Fix focus loss shrink issue
* PosterRating: Only add extra padding when is-minimal
So we don't alter the spacing when this component is used on an actual posters
.small-scrollbar is used on poster rating/status lists, but wasn't working because we also have the `scrollbar-width` property set, so now if the browser supports the webkit scrollbar styling, we will prefer that over scrollbar-width.
Don't know if this will break safari or whatever but hell if ima download that.
firefox scrollbar looks nice and this will let us keep using scrollbar-width: small wherever we want for that sweet smol bar action in ff
The inner container is not helpful for highlighting when tabbing through posters. The title of poster can still be used to enter the content via keyboard, the inner container did the same thing so was redundant and only added an extra click for any navigating via keyboard.
more control = need to be able to move it in js.
Still supports using ::before, so not all menus need updating and can stay simple, just the menus needing more control can start using an actual element for the arrow.
Currently will only shift elements back into view if out of bounds on the left.
Not necessary at the moment to support oob on other sides, or support resizing to fit. Maybe in the future when it's used more.
* test-pr.yml: Add format_check_go job
* separate test-pr into two files for client and server
so we can set the `paths` property and make the jobs only run when changes are detected for the client or server
* test breaking formatting
* correct formatting
* test-pr-server.yml: uncomment yml path
test has succeeded
We now wait for the save request to complete before unfocusing the stars, which avoids the jitter where it snaps back to actual rating before snapping to new rating when it finally saves
Is smaller when the media query makes the letter-spacing smaller. If i need to change this again, might be better to get it dynamically, but on component load and window resize instead of in each func call?
- Moved ExtraDetails (from Poster and GamePoster) to its own component for reuse, also no longer one line.
- Consolodated ExtraDetails and ExtraDetailsGame types into one type: PosterExtraDetails.
- Created Rating helpers lib. Contains: toShowableRating() and toWhichThumb()
- Fix extra detail dates not listing for games on search page
Instead of trying to center the rating text element ourselves by using its width/2, we can just simply rely on the tranlateX -50% style instead of removing it.
Seems to actually be accurate for what we need, I think we should just use float64 instead of importing a library for decimal values (if it continues working and i find no more issues)
Because of a bug with mouseleave tirggering when a star is clicked directly and browser focused at same time.
Also renamed handleStarHoverEnd->handleRatingHoverEnd since its now on the rating wrap element instead of a star element
Most of the client work is done:
- Added new RatingSystem and RatingStep settings
- Rating component now supports all systems and steps (minus thumbs)
Thumbs and server work for saving user setting and then testing! yupee
* Save requested season number in `LastViewedSeason` property
When season details are requested and a watchedId is passed as a query parameter, the requested season number is now saved in the watched entries `LastViewedSeason` property.
* SeasonsList: Restore activeSeason and update state after request with new lastViewedSeason value
* get season details route: add extra log for else case where no watchedId is found
Makes it easier when accessing the vite dev server from outside the local machine, instead of making me change the variable to my machines local ip all the time
* wip
* wip
* wip
* wip (also update go version)
* wip
* wip
* wip looks like its working
* increase job done time before deletion
30m seems more reasonable?
When a search request is running, and the query is changed, the previous request cancellation would hide the loader just after the new request started loading, resulting in the loader being hidden for the duration of the request being completed. Now the loader will only hide if the request errors, not for cancellations too which was causing this issue
* Initial implementation of ryot import process
* Bug fixes for movie imports and show ratings
* Cleanup
* Added Ryot's logo to import button
* Ryot import now supports the DROPPED flag for shows
* Formatted the code and added restrictions for tv shows and movies only
* Better units
* Prettier format
* Fix type errors, change stat styling to push value down
---------
Co-authored-by: IRHM <37304121+IRHM@users.noreply.github.com>
Has always been set as HOLD from frontend apparently, never used this value before on server so must've missed it (until now, i wasted a lot of time ;().
We weren't ensuring that the whole watched season object was set to hookResponse.WatchedSeason first, so they client wouldn't get the WatchedSeason `id` (so couldn't update the season).
* Support emby branding
Swap out jellyfin branding for emby when USE_EMBY is enabled.
* Server: Change jellyfin host setting text to emby when USE_EMBY enabled
basically buddy, if you search for something and filter for 'movies' (for example), then you change the search to something else, but no movies come up in the results, the 'movies' filter would hide, but still be active. That was confusing behavour, so now the button 'movies' in this case will always stay visible, if it's the active filter.
* Search: Add filters (for content type), remove terrible result sort, dynamic page title
* Search: Better responsiveness for filters
Moving margin to wrapper and adding to right makes it wrap sooner.
* Search: Even better responsiveness for filters
On smaller screens, changes flex-flow to column and centers buttons
to avoid thought changes being lost if the server fails when saving.
Also stopped saving changed on blur of textarea, now only saves when close modal is clicked.
* Country support for watch providers (#1, not functional)
* frontend dropdowns now actually read and write the correct setting
* user country setting now respects the server side default when creating a new user
* watch providers correctly show based on country, but changing the coutnry requires restarting the container to take effect
* flushing cache when updating user settings
* non functional, initial support for getting all the countries of which tmdb has streaming providers for to let users pick one
* users get shown a list of country codes to pick from and the selection gets saved and used, but the dropdown menu doesn't allow for scrolling
* limited dropdown height and auto scroll to the letter the user hits
* simplified auto scroll code
* the dropdown to choose countries now shows their full english name
* server/user region improvements
* DropDown: remove console log
used to test
* DropDown: Add keypress event listener on main div
instead of document body, so only triggered when key pressed whilst focused on dropdown.
---------
Co-authored-by: Stig <stig.narnia@gmail.com>
Co-authored-by: IRHM <37304121+IRHM@users.noreply.github.com>
* Issue #130
* Watcharr import: support activity import and fix ImportedList data
Also added padding to bottom of import page
---------
Co-authored-by: John Stephani <me@johnstephani.com>
Co-authored-by: IRHM <37304121+IRHM@users.noreply.github.com>
fetches data again, because I'm too lazy to make it work locally. Also don't think it's that crucial just for an admin page to make it super duper deliciouso at the el momento
So we can only apply then when the PosterList is in wrapping mode.
Added default min-width to posters of 170px.
This fixes posters on other pages, where they would be super small.
We now have two search bars in the markup to make this easily possible. When the size of the main input becomes too small to see the placeholder, we hide it and show another search bar below the main nav content.
Small range where we have a dynamic size to hopefully work better on a bigger range of devices. Can't go too big or too small otherwise the posters can become ugly and unusable.
Works well now with all the preset device sizes in my browser.
If we can get an auth token for our home server, then the user must have access to it.
plexUserHasAccessToPlexHost method wouldn't work if our plex server had zero allowed users (except ourselves), since the data would not appear for ourself.
<!-- It's harder to track bugs when multiple are reported in one issue. If you have more than one (unrelated) bugs to report, please make one issue per bug. -->
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Platform (please complete the following information):**
<!-- Feature requests can be hard to track when two or more unrelated ideas are included in one issue. Please make a new issue for each idea (make as many as you need to). -->
**Idea Overview**
A quick overview of the idea you are proposing.
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
about: Help us with our documentation. Is something important missing?
title: ""
labels: documentation
assignees: IRHM
---
<!-- Did you know: You can click `Edit this page` at the bottom of any page on the docs to propose exact changes? If this doesn't apply to you, continue below and fill out the issue. -->
**What is missing or needs updating on the documentation site?**
Please describe in detail what is missing or needs updating on the documentation site.
**(optional) How would you write/update this doc?**
We haven't rebuilt the wheel from scratch, here are the tools that have helped this project come to fruition.
(I am creating this file a bit late, some tools may be missing, hopefully over time I can get everything listed here).
## Web Client
Look at our [package.json](./package.json) for the packages we directly use.
- [Ionicons](https://ionic.io/ionicons) When looking for high quality icons, I go here first. Most of the icons in Watcharr are from here.
- [Wikimedia Commons](https://commons.wikimedia.org) For [Streaming provider icons](https://commons.wikimedia.org/wiki/Category:SVG_logos_of_video_streaming_services).
- [Penpot](https://github.com/penpot/penpot) For initial UI design and creating the logo.
- [Google Fonts](https://fonts.google.com/) For custom fonts and for a few icons too. Don't worry though, fonts/icons are included in the Watcharr download, there are **no** requests made to google.
## Server
Look at our [go.mod](./server/go.mod) for the packages we use.
@@ -18,43 +18,60 @@ I am built with Go and Svelte(Kit).
Feel free to abuse this demo instance (nicely), which runs on the latest `dev` build (there may be bugs, as new features are tested on here too): [https://beta.watcharr.app/](https://beta.watcharr.app/)
[Track Progress Until Next Version](https://github.com/orgs/sbondCo/projects/9/views/3)
[Track progress for the next version](https://github.com/orgs/sbondCo/projects/9/views/3).
[Checkout our documentation](https://watcharr.app/docs/category/installation) for an up to date guide on setup! If you hate manuals, but love docker, this [docker-compose.yml](./docker-compose.yml) file is your friend.
[Checkout our documentation](https://watcharr.app/docs/category/installation) for an up to date guide on setup! If you hate manuals, but love docker, this [compose.yml](./compose.yml) file is your friend.
# Community Made Tools
Third-party tools made by the community for enhancing your Watcharr experience!
- [Kodi Plugin](https://github.com/airdogvan/watcharr_kodi) by [airdogvan](https://github.com/airdogvan) for automatically tracking your watched shows/movies.
Thanks to anyone that has made a script or tool for Watcharr. Feel free to add your own to the list if you have one!
**Note:** I cannot provide any assurances for these tools or stay on top of them (code review, etc), if you have any problems please open an issue in the project for the tool so that they can stay organized.
# Getting Help
If something isn't working for you or you are stuck, [creating an issue](https://github.com/sbondCo/Watcharr/issues/new) is the best way to get help! Every type of issue is accepted, so don't be afraid to ask anything!
You can also [join our space on Matrix](https://matrix.to/#/#watcharr:matrix.org) for support.
# Contributing
Please continue to our [contributing guide](CONTRIBUTING.md).
**Please do not report security vulnerabilities through public GitHub issues.**
You can reach out directly to [@irhm:matrix.org](https://matrix.to/#/@irhm:matrix.org) on matrix to discuss the vulnerability or you may [draft a new security advisory on this repository](https://github.com/sbondCo/Watcharr/security/advisories/new).
You may consider a backup of your server before starting any import. They are not easily reversible, though we do our best to ensure they are accurate and bug free!
:::
1. Export your list from MyAnimeList at: https://myanimelist.net/panel.php?go=export

2. Save the export anywhere and extract it to get your export `.xml` file.
description: Install and setup with Docker Compose for access through a subpath.
---
# Docker Compose (subpath)
Install and setup with Docker Compose for access through a subpath.
:::info Not a great experience at the moment!
Currently, hosting Watcharr via a subpath on your server is not very easy (unlike hosting under a subdomain). Hopefully this will change in the future, but as a temporary measure to at least allow hosting under a subpath, this method has been provided.
The following issue will continue to track this: https://github.com/sbondCo/Watcharr/issues/312
:::
## Installing
### Build UI
First we have to build the frontend with our subpath provided as an environment variable.
If you don't want to use `/watcharr` as your subpath, replace the value of `WATCHARR_BASE` before running the command.
```bash
docker run -e WATCHARR_BASE=/watcharr -v watcharr-ui:/ui --rm ghcr.io/sbondco/watcharr-ui-build:latest
```
Once the container has finished running the build script, it will exit and remove itself. The `watcharr-ui` volume will contain the built files.
### Install Watcharr
Now we can install Watcharr. You can copy the example below to get started:
```yaml title="compose.yml"
services:
watcharr:
# The :latest tag is used for simplicity, it is recommended
# to use an actual version, then when updating check the releases for changelogs.
image: ghcr.io/sbondco/watcharr:latest
container_name: watcharr
ports:
- 3080:3080
volumes:
# Contains all of watcharr data (database & cache)
- ./data:/data
# Use our volume containing built ui files
# instead of default ui included in image.
- type: volume
source: watcharr-ui
target: /ui
volume:
nocopy: true
subpath: build
restart: unless-stopped
volumes:
watcharr-ui:
external: true
```
:::danger first account
When **first** running Watcharr, make sure only you have access. The first user created will become admin.
:::
You can now start `Watcharr` like so:
```bash
docker compose up -d
```
If you didn't change the ports in the example, the server will be available at [http://localhost:3080/](http://localhost:3080/).
## Updating
:::danger Take care
We try taking care as to not release breaking changes, however it is still recommended that
you lookover changelogs before updating!
Breaking changes are marked at the top of releases: https://github.com/sbondCo/Watcharr/releases
:::
1. Update your built ui files by following the [Build UI](#build-ui) step again.
2. Update the `image` version in your `compose.yml` file.
Skip this step if you are using the `latest` tag.
```yaml
# eg. update v1.19.0 to v1.20.0 (or whatever version you are updating to)
image: ghcr.io/sbondco/watcharr:v1.19.0
```
3. Pull the new changes and re-create your container:
```bash
docker compose pull && docker compose down && docker compose up -d
description: Building from source for developing upon Watcharr.
---
# For Development
This guide will help you setup Watcharr for development in your local environment.
## Setup
This section assumes you will be forking the repo on Github, of course you can alter this section to work with your workflow, but if you intend to create a pull request with your work, it may be difficult if you're not also using Github (I don't know :()).
1. Fork the repository
On GitHub you can fork the repository with the 'Fork' button at the top.
You only need to do this once after pulling the codebase for the first time, and again every time the dependencies are changed/updated.
1. Install frontend dependencies (in the project root folder)
```
npm i
```
2. Install server dependencies (in the `server` folder)
```
go get .
```
## Running The Code
To run the code, you will need to open up two terminals, one for the frontend and the other for the backend.
1. Run the frontend (first terminal, in the project root folder)
```bash
npm run dev
```
2. Run the server (second terminal, in the project root folder)
```bash
npm run server
```
**Note:** If you're using Windows, running the server can be a little more complicated. You can follow this: https://github.com/sbondCo/Watcharr/discussions/430#discussioncomment-8894110 which amounts to these steps (the first 3 steps only need to be done once):
1. Set CGO_ENABLED environment variable with go
```
go env -w CGO_ENABLED=1
```
2. Install `gcc` (if you don't already have it installed) from https://jmeubank.github.io/tdm-gcc/ (found from this answer on stackoverflow: https://stackoverflow.com/a/43588236).
3. Install server dependencies again with `go get .` in the `server` folder.
4. Manually run the server, setting the MODE environment variable in powershell (from the `server` folder)
```
cmd /V /C "set MODE=DEV&& go run ."
```
3. Visit [http://localhost:5173/](http://localhost:5173/) and setup Watcharr.
Watcharr cannot handle backing up for you, but its simple structure should make it easy to slide it into your existing backup routine.
Once you have created your first backup, it's recommended that you try restoring from that backup to make sure everything is correct and will work in case you need to restore from it in the future.
:::danger Shutdown your server!
Always shutdown Watcharr before backing up its data, otherwise you run the risk of corrupting files (mainly your database).
:::
## Simple Steps
:::success Recommended
This is the recommended way to backup.
:::
Here are the steps that are run daily for the `beta.watcharr.app` instance.
1. Shutdown Watcharr.
2. Copy and backup the entire `data` folder (default location is `./data`, backup whichever folder your server is configured to store its data in).
3. Start Watcharr.
I call these the simple steps because they simply backup your entire server, if you ever need to restore your server, it will start up from its exact state at backup.
## Advanced Steps
:::danger Discouraged
Backing up this way is discouraged because new important files could be added later and missed.
:::
If you don't care about the warning not to backup this way, here are the "important" files that you can single out for backup:
-`watcharr.db` Your database, holds all users, their watchlists, etc.
-`watcharr.json` Server config.
-`img/up` Profile picture uploads.
-`img/games` Game posters (not exactly important, but scenarios in which this folder is not backed up have not been tested, only relevant for servers with game support enabled).
description: All environment variables you can use to start your server in a specific way.
---
# Environment Variables
Currently there is only one, and maybe it will stay that way forever (because the admin interface can handle most settings). A very lonely page right now ;(.
## `WATCHARR_DATA`
Make Watcharr use a custom directory for all of its data.
Game support in Watcharr, currently, must be enabled by you.
This involves setting up a Twitch developer account (phone number needed for 2FA which is required) and entering application credentials into Watcharr, that can then be used for looking up game info via IGDB.
P.S. These steps are stolen from [igdb api docs](https://api-docs.igdb.com/#account-creation), I've tried to make it easier to follow with screenshots.
description: Getting admin privileges for your account without already having access to an account with admin.
---
# Restoring Admin Priviliges
This guide will help you restore/give admin access to any account without needing an account with admin. If you ever accidentally remove your permissions, this is the easiest way to get them back.
All you will need is access to the `watcharr.log` file.
## Steps
1. Login with the account you'd like to give admin to.
2. Navigate to the `/request_admin` page manually (ex: `127.0.0.1:3080/request_admin`) and click the `request` button.

3. Check your `watcharr.log` file (or simply check `docker compose logs` if using docker compose) and look for the generated admin token (highlighted in the image below).

4. Enter the code from the log (you should have been taken here after clicking the request button in step 2).
slog.Error("loginPlex: Failed to get home server auth token for user! If not because the request failed, then ensure the user has access to our home servers library.","error",err)
returnAuthResponse{},errors.New("failed to verify plex access")
}
dbUser:=new(User)
userIdQ:=db.Select("user_id").Where("name = ? AND client_id = ?","plex",account.Id).Table("user_services")
addJobError(jobId,userId,fmt.Sprintf("episode rating of %d for %s not imported. The episode does not exist in your history or watchlist.",v.Rating,title))
}
}else{
mv.Rating=float64(v.Rating)
toImport[mapKey]=mv
}
}else{
// Item should be in toImport by now (from history or watchlist) if it has a rating, otherwise we won't import it
addJobError(jobId,userId,fmt.Sprintf("cannot import rating of %d for %s. The main content does not exist in your history or watchlist. type: %s traktSlug: %s",v.Rating,title,v.Type,traktSlug))
}
}
}
// Loop over `toImport` and finally import everything.
for_,v:=rangetoImport{
_,err:=importContent(db,userId,v)
iferr!=nil{
slog.Error("startTraktImport: Failed to do import on content!","error",err,"import_obj",v)
addJobError(jobId,userId,fmt.Sprintf("Failed to import %s as %s. tmdbId: %d",v.Type,v.Status,v.TmdbID))
slog.Debug("processTraktHistoryItem: Processing an episode.","showTitle",title,"season",v.Episode.Season,"episode",v.Episode.Number)
}else{
slog.Debug("processTraktHistoryItem: Processing a show.","contentTitle",title,"contentTmdbId",tmdbId)
}
}elseifv.Type=="movie"{
title=v.Movie.Title
traktId=v.Movie.Ids.Trakt
tmdbId=v.Movie.Ids.Tmdb
contentType=MOVIE
slog.Debug("processTraktHistoryItem: Processing a movie.","contentTitle",title,"contentTmdbId",tmdbId)
}
iftmdbId==0{
slog.Debug("processTraktHistoryItem: Item had no tmdbId. Cannot process.")
returnerrors.New("Failed to process history: "+title+" type:"+v.Type+" trakt id:"+strconv.Itoa(traktId)+" tmdb id:"+strconv.Itoa(tmdbId)+" error:"+"item had no tmdb id")
slog.Error("traktAPIRequest: non 2xx status code:","status_code",res.StatusCode)
returnmap[string][]string{},errors.New("non success status code")
}
err=json.Unmarshal([]byte(body),&resp)
iferr!=nil{
returnmap[string][]string{},err
}
returnres.Header,nil
}
functraktImportWatched(
db*gorm.DB,
userIduint,
traktUsernamestring,
)(TraktImportResponse,error){
jobId,err:=addUniqueJob("trakt_import",userId)
iferr!=nil{
slog.Error("traktSyncWatched: Failed to create a job","error",err)
returnTraktImportResponse{},err
}
updateJobStatus(jobId,userId,JOB_RUNNING)
gostartTraktImport(
db,
jobId,
userId,
traktUsername,
)
returnTraktImportResponse{JobId:jobId},nil
}
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.