Skip to content

Commit

Permalink
Merge pull request #396 from madeofpendletonwool/user-containers
Browse files Browse the repository at this point in the history
User containers
  • Loading branch information
madeofpendletonwool authored Jan 19, 2025
2 parents c78f3bf + 41388ab commit 36db6d6
Show file tree
Hide file tree
Showing 11 changed files with 272 additions and 29 deletions.
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,15 @@ First, the server. You have multiple options for deploying Pinepods:
You can also choose to use MySQL/MariaDB or Postgres as your database. Examples for both are provided below.

### Docker Compose
#### User Permissions
Pinepods can run with specific user permissions to ensure downloaded files are accessible on the host system. This is controlled through two environment variables:
- `PUID`: Process User ID (defaults to 1000 if not set)
- `PGID`: Process Group ID (defaults to 1000 if not set)

To find your user's UID and GID, run:
```bash
id -u # Your UID
id -g # Your GID

#### Compose File - PostgreSQL (Recommended)
```yaml
Expand Down Expand Up @@ -106,6 +115,8 @@ services:
VALKEY_PORT: 6379
# Enable or Disable Debug Mode for additional Printing
DEBUG_MODE: false
PUID: ${UID:-911}
PGID: ${GID:-911}
volumes:
# Mount the download and backup locations on the server
- /home/user/pinepods/downloads:/opt/pinepods/downloads
Expand Down Expand Up @@ -160,6 +171,9 @@ services:
VALKEY_PORT: 6379
# Enable or Disable Debug Mode for additional Printing
DEBUG_MODE: false
PUID: ${UID:-911}
PGID: ${GID:-911}
volumes:
# Mount the download and backup locations on the server
- /home/user/pinepods/downloads:/opt/pinepods/downloads
Expand Down
9 changes: 5 additions & 4 deletions completed_todos.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,14 @@ Version 0.7.3


- [ ] Container can be ran as host machine user
- [ ] Nextcloud Sync Fixed
- [ ] Episode Completion Status is now pushed to Nextcloud/Gpodder
- [x] Nextcloud Sync Fixed
- [x] Episode Completion Status is now pushed to Nextcloud/Gpodder
- [x] Adjusted Downloaded Episode titles to be more descriptive - Also added metadata
- [ ] Fixed issue with news feed adding
- [ ] Additional Podcast parsing when things are missing
- [x] Additional Podcast parsing when things are missing
- [ ] Add pinepods news feed to any admin rather than hard id of 2
- [ ] Fix recent episodes so it handles incompletes better
- [x] Fix recent episodes so it handles incompletes better
- [ ] Check mark episode complete on episode page

Version 0.7.2

Expand Down
44 changes: 36 additions & 8 deletions database_functions/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2716,10 +2716,24 @@ def download_podcast(cnx, database_type, episode_id, user_id): # Fixed paramete
cursor.close()
return False

episode_url = get_value(result, "EpisodeURL")
podcast_name = get_value(result, "PodcastName")
episode_title = get_value(result, "EpisodeTitle")
pub_date = get_value(result, "EpisodePubDate")
# Get values based on result type
if isinstance(result, dict):
episode_url = result.get('episodeurl') or result.get('EpisodeURL')
podcast_name = result.get('podcastname') or result.get('PodcastName')
episode_title = result.get('episodetitle') or result.get('EpisodeTitle')
pub_date = result.get('episodepubdate') or result.get('EpisodePubDate')
author = result.get('author') or result.get('Author')
episode_artwork = result.get('episodeartwork') or result.get('EpisodeArtwork')
artwork_url = result.get('artworkurl') or result.get('ArtworkURL')
else:
# Match positions from SELECT query
episode_url = result[4] # EpisodeURL
podcast_name = result[7] # PodcastName
episode_title = result[2] # EpisodeTitle
pub_date = result[3] # EpisodePubDate
author = result[8] # Author
episode_artwork = result[6] # EpisodeArtwork
artwork_url = result[9] # ArtworkURL

# Get user's time and date preferences
timezone, time_format, date_format = get_time_info(database_type, cnx, user_id)
Expand Down Expand Up @@ -2749,6 +2763,9 @@ def download_podcast(cnx, database_type, episode_id, user_id): # Fixed paramete
# Create the download directory
download_dir = os.path.join("/opt/pinepods/downloads", podcast_name)
os.makedirs(download_dir, exist_ok=True)
uid = int(os.environ.get('PUID', 1000))
gid = int(os.environ.get('PGID', 1000))
os.chown(download_dir, uid, gid)

# Generate filename with enhanced details
filename = f"{pub_date_str}_{episode_title}_{user_id}-{episode_id}.mp3"
Expand Down Expand Up @@ -2798,6 +2815,11 @@ def download_podcast(cnx, database_type, episode_id, user_id): # Fixed paramete
for chunk in response.iter_content(chunk_size=1024):
f.write(chunk)

uid = int(os.environ.get('PUID', 1000))
gid = int(os.environ.get('PGID', 1000))
os.chown(file_path, uid, gid)
os.chown(download_dir, uid, gid)

# After successful download, add metadata
metadata = {
'title': episode_title,
Expand Down Expand Up @@ -6481,15 +6503,21 @@ def get_time_info(database_type, cnx, user_id):
cursor.close()

if result:
if database_type == "postgresql":
return result['timezone'], result['timeformat'], result['dateformat']
# Check if result is a dict or tuple
if isinstance(result, dict):
# Handle both postgres (lowercase) and mysql (uppercase) dict keys
timezone = result.get('timezone') or result.get('Timezone')
timeformat = result.get('timeformat') or result.get('TimeFormat')
dateformat = result.get('dateformat') or result.get('DateFormat')
else:
return result['Timezone'], result['TimeFormat'], result['DateFormat']
# Handle tuple result (order should match SELECT query)
timezone, timeformat, dateformat = result

return timezone, timeformat, dateformat
else:
return None, None, None



def first_login_done(database_type, cnx, user_id):
if database_type == "postgresql":
from psycopg.rows import dict_row
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ services:
VALKEY_PORT: 6379
# Enable or Disable Debug Mode for additional Printing
DEBUG_MODE: False
PUID: ${UID:-911}
PGID: ${GID:-911}
volumes:
# Mount the download and the backup location on the server if you want to. You could mount a nas to the downloads folder or something like that.
# The backups directory is used if backups are made on the web version on pinepods. When taking backups on the client version it downloads them locally.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ services:
VALKEY_PORT: 6379
# Enable or Disable Debug Mode for additional Printing
DEBUG_MODE: False
PUID: ${UID:-911}
PGID: ${GID:-911}
volumes:
# Mount the download location on the server if you want to. You could mount a NAS to this folder or something similar
- /home/user/pinepods/downloads:/opt/pinepods/downloads
Expand Down
5 changes: 4 additions & 1 deletion startup/startup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,10 @@ supervisord -c /pinepods/startup/supervisordebug.conf
else
supervisord -c /pinepods/startup/supervisord.conf
fi
# Create Admin User

chown -R ${PUID}:${PGID} /opt/pinepods/downloads
chown -R ${PUID}:${PGID} /opt/pinepods/backups

# python3 /pinepods/create_user.py $DB_USER $DB_PASSWORD $DB_HOST $DB_NAME $DB_PORT "$FULLNAME" "$USERNAME" $EMAIL $PASSWORD
# Store the PID of supervisord
child=$!
Expand Down
2 changes: 2 additions & 0 deletions web/src/components/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ pub struct AppState {
pub youtube_search_results: Option<YouTubeSearchResults>,
pub selected_youtube_channel: Option<YouTubeChannel>,
pub is_youtube_loading: Option<bool>,
pub show_transcript_modal: Option<bool>,
pub current_transcripts: Option<Vec<Transcript>>,
}

#[derive(Default, Deserialize, Clone, PartialEq, Store, Debug)]
Expand Down
Loading

0 comments on commit 36db6d6

Please sign in to comment.