Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Komga implementation #943

Merged
merged 70 commits into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from 64 commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
4f15900
komga implementation
Jacob-Tate Aug 2, 2024
b5b39cd
Updated Komga integration to use SSE
Jacob-Tate Aug 4, 2024
238b146
Merge branch 'IgnisDa:main' into komga_impl
Jacob-Tate Aug 4, 2024
0e1c957
Finalizing implementation
Jacob-Tate Aug 5, 2024
83105fe
Added Komga Documentation
Jacob-Tate Aug 5, 2024
9fc4687
Placed Cargo.toml in Alphabetic Order
Jacob-Tate Aug 8, 2024
6bd89bd
Merge branch 'IgnisDa:main' into komga_impl
Jacob-Tate Aug 8, 2024
3e1f70a
Changed Komga into a Yank Integration.
Jacob-Tate Aug 8, 2024
86e2c5c
Removed provider specifics as it wasnt really needed.
Jacob-Tate Aug 8, 2024
b43df5b
Reverted order
Jacob-Tate Aug 8, 2024
834f3ff
Updated komga documentation
Jacob-Tate Aug 8, 2024
fb43a33
Fixed a bug where some manga have imported with the incorrect number
Jacob-Tate Aug 8, 2024
0b38409
docs: address formatting issues
IgnisDa Aug 9, 2024
6ab65c4
build(backend): pin `eventsource-stream` version
IgnisDa Aug 9, 2024
5aab4c8
chore(backend): format files
IgnisDa Aug 9, 2024
828ef34
refactor(backend): move integration to dedicated folder
IgnisDa Aug 9, 2024
a7a2b55
Fixed a bug where some tachiyomi clients report in random order.
Jacob-Tate Aug 10, 2024
8920c8a
Removed provider specifics from UpdateUserInntegrationInput
Jacob-Tate Aug 10, 2024
647cf47
Merge remote-tracking branch 'refs/remotes/origin/main' into komga_impl
Jacob-Tate Aug 10, 2024
ff38c8c
Fixed order of includes to match original.
Jacob-Tate Aug 10, 2024
ebd9be3
Fixed order of imports for komga.rs
Jacob-Tate Aug 10, 2024
54cd048
chore(backend): run formatter
IgnisDa Aug 11, 2024
94ba3f6
chore(backend): some housekeeping
IgnisDa Aug 11, 2024
57bff2d
fix(backend): type checks
IgnisDa Aug 11, 2024
ba0980d
chore(backend): add newline
IgnisDa Aug 11, 2024
72157b4
feat(backend): yank integrations data right on application startup
IgnisDa Aug 11, 2024
ecaf309
chore(backend): add a debug statement
IgnisDa Aug 11, 2024
30c9b78
Removed Option from find_provider_and_id
Jacob-Tate Aug 11, 2024
bc28164
Merge branch 'main' into komga_impl
IgnisDa Aug 11, 2024
302cb13
Run CI Empty Commit
Jacob-Tate Aug 11, 2024
afd70a8
chore: empty commit
IgnisDa Aug 12, 2024
c4070e3
ci: additional check for maintainer
IgnisDa Aug 14, 2024
5112364
merge origin
Jacob-Tate Aug 17, 2024
3d21694
Komga Implementation
Jacob-Tate Aug 17, 2024
703dc30
Merge branch 'refs/heads/komga' into komga_impl
Jacob-Tate Aug 17, 2024
1b02fc5
Resolve merge errors
Jacob-Tate Aug 17, 2024
4469588
Merge branch 'komga_impl' of https://github.com/jacob-tate/ryot into …
IgnisDa Aug 17, 2024
5c9c4f0
ci: revert ci changes
IgnisDa Aug 17, 2024
01f8d7f
chore(integrations): import structure
IgnisDa Aug 17, 2024
f2397b1
build(integrations): remove uneeded package
IgnisDa Aug 17, 2024
cc8178d
ci: change computation of image names
IgnisDa Aug 17, 2024
36bd0e3
ci: hardcode docker username
IgnisDa Aug 17, 2024
3180b9b
ci: enable hardmode
IgnisDa Aug 17, 2024
9b37a40
ci: quote names
IgnisDa Aug 17, 2024
6f6c2c9
ci: no heredoc fuckery
IgnisDa Aug 17, 2024
e3e0905
ci: change name of image
IgnisDa Aug 17, 2024
dd54876
ci: remove docker for forks
IgnisDa Aug 17, 2024
12cae01
ci: update condition
IgnisDa Aug 17, 2024
eccf2c4
ci: logging
IgnisDa Aug 17, 2024
6debb41
ci: use gh actions script
IgnisDa Aug 17, 2024
a9d23bb
ci: print all outputs
IgnisDa Aug 17, 2024
ea960dc
ci: use correct image names
IgnisDa Aug 17, 2024
c41b365
ci: use correct owner name
IgnisDa Aug 17, 2024
ba08f71
Upgraded to a trait model
Jacob-Tate Aug 17, 2024
fe023cd
Migrated jellyfin to trait
Jacob-Tate Aug 17, 2024
2834ac2
Fixed visibility of function
Jacob-Tate Aug 17, 2024
0f528a2
Emby Integration Migration
Jacob-Tate Aug 17, 2024
110d25c
Plex Integration Migration
Jacob-Tate Aug 17, 2024
bc5dfcc
Audiobookshelf Integration Migration (partial)
Jacob-Tate Aug 17, 2024
45db825
Kodi Integration Migration
Jacob-Tate Aug 18, 2024
5f131ed
Sonarr Integration Migration
Jacob-Tate Aug 18, 2024
be9c608
Radarr Integration Migration
Jacob-Tate Aug 18, 2024
3fc61c0
Ran formatter
Jacob-Tate Aug 18, 2024
8ecc8a6
chore: run rust formatter
IgnisDa Aug 18, 2024
79c6c05
refactor(integrations): some import changes
IgnisDa Aug 18, 2024
6715016
Finished implementing Audiobookshelf
Jacob-Tate Aug 18, 2024
3eebdb4
Undid accidental change
Jacob-Tate Aug 18, 2024
2394396
Merge branch 'IgnisDa:main' into komga_impl
Jacob-Tate Aug 19, 2024
ec018ed
chore(backend): apply formatter
IgnisDa Aug 19, 2024
c1eba11
Merge branch 'main' into komga_impl
IgnisDa Aug 19, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 48 additions & 28 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,36 +20,56 @@ jobs:
pre-workflow-checks:
runs-on: ubuntu-latest
outputs:
should-run: ${{ steps.check.outputs.should-run }}
should-release: ${{ steps.tag.outputs.should-release }}
should-run: ${{ steps.set_outputs.outputs.should-run }}
image-names: ${{ steps.set_outputs.outputs.image-names }}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vnghia I have been trying to get this working for some time, but it seems that there is no way to publish a docker image from a PR (from a fork) since the GITHUB_TOKEN granted to the workflow only has read permissions (despite specifying write explicitly in the action).

Do you know a solution to this?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the current flow never works for PRs. Only for PRs from a branch in the same repo.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let me think about it. you can use env instead of secrets but it will print your env in the log

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But to actually inject the secrets into env, i would still need access to secrets. Which are not available in PRs from forks.

should-release: ${{ steps.set_outputs.outputs.should-release }}

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Check commit message
id: check
run: |
if [[ "${{ github.event_name }}" == "push" ]]; then
echo "should-run=true" >> $GITHUB_OUTPUT
elif [[ "${{ github.event_name }}" == "pull_request" ]]; then
COMMIT_MSG=$(git log --format=%B ${{ github.event.pull_request.head.sha }})
if [[ "$COMMIT_MSG" == *"Run CI"* ]]; then
echo "should-run=true" >> $GITHUB_OUTPUT
else
echo "should-run=false" >> $GITHUB_OUTPUT
fi
else
echo "should-run=false" >> $GITHUB_OUTPUT
fi
- name: Check tag
id: tag
run: |
if [[ "${{ github.event_name }}" == "push" && "${{ github.ref }}" == "refs/tags/${{ github.ref_name }}" ]]; then
echo "should-release=true" >> $GITHUB_OUTPUT
else
echo "should-release=false" >> $GITHUB_OUTPUT
fi
- name: Set outputs
id: set_outputs
uses: actions/github-script@v7
with:
script: |
const repositoryName = context.payload.repository.name;
const owner = context.repo.owner;
const ghcrRegistry = process.env.GHCR_REGISTRY;
const dockerUsername = process.env.DOCKER_USERNAME;

let imageNames = [
`name=${dockerUsername}/${repositoryName}`,
`name=${ghcrRegistry}/${owner}/${repositoryName}`
];

if (context.eventName === "push") {
core.setOutput('should-run', 'true');
} else if (context.eventName === "pull_request") {
const commitMsg = await github.rest.repos.getCommit({
owner: context.repo.owner,
repo: context.repo.repo,
ref: context.payload.pull_request.head.sha
}).then(commit => commit.data.commit.message);
if (commitMsg.includes("Run CI")) {
core.setOutput('should-run', 'true');
if (context.payload.pull_request.head.repo.full_name !== context.repo.full_name) {
imageNames.shift();
}
} else {
core.setOutput('should-run', 'false');
}
} else {
core.setOutput('should-run', 'false');
}

if (context.eventName === "push" && context.ref.startsWith("refs/tags/")) {
core.setOutput('should-release', 'true');
} else {
core.setOutput('should-release', 'false');
}

core.setOutput('image-names', imageNames.join('\n'));

create-release:
needs:
Expand Down Expand Up @@ -187,22 +207,22 @@ jobs:
uses: docker/setup-buildx-action@v3
- name: Log in to the ghcr container registry
uses: docker/login-action@v3
continue-on-error: true
with:
registry: ${{ env.GHCR_REGISTRY }}
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Log in to the docker hub container registry
uses: docker/login-action@v3
continue-on-error: true
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}
- name: Extract metadata for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: |
name=${{ secrets.DOCKER_USERNAME }}/${{ github.event.repository.name }}
name=${{ env.GHCR_REGISTRY }}/${{ github.repository_owner }}/${{ github.event.repository.name }}
images: ${{ needs.pre-workflow-checks.outputs.image-names }}
tags: |
type=ref,event=pr
type=raw,value=develop,enable={{is_default_branch}}
Expand Down
13 changes: 13 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions apps/backend/src/job.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ pub async fn sync_integrations_data(
_information: ScheduledJob,
misc_service: Data<Arc<MiscellaneousService>>,
) -> Result<(), Error> {
tracing::trace!("Getting data from yanked integrations for all users");
misc_service.yank_integrations_data().await.unwrap();
misc_service.sync_integrations_data().await.unwrap();
Ok(())
}

Expand Down Expand Up @@ -118,6 +117,7 @@ pub async fn perform_application_job(
.deploy_update_exercise_library_job()
.await
.is_ok(),
ApplicationJob::SyncIntegrationsData => misc_service.sync_integrations_data().await.is_ok(),
};
tracing::trace!(
"Job: {:#?}, Time Taken: {}ms, Successful = {}",
Expand Down
5 changes: 5 additions & 0 deletions apps/backend/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,11 @@ async fn main() -> Result<()> {
)
.await;

perform_application_job_storage
.enqueue(ApplicationJob::SyncIntegrationsData)
.await
.unwrap();

if Exercise::find().count(&db).await? == 0 {
tracing::info!("Instance does not have exercises data. Deploying job to download them...");
perform_application_job_storage
Expand Down
38 changes: 37 additions & 1 deletion apps/frontend/app/routes/_dashboard.settings.integrations.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
DeleteUserIntegrationDocument,
GenerateAuthTokenDocument,
IntegrationProvider,
MediaSource,
UpdateUserIntegrationDocument,
UserIntegrationsDocument,
type UserIntegrationsQuery,
Expand All @@ -53,7 +54,10 @@ import { commaDelimitedString, dayjsLib } from "~/lib/generals";
import { useConfirmSubmit, useUserCollections } from "~/lib/hooks";
import { createToastHeaders, serverGqlService } from "~/lib/utilities.server";

const YANK_INTEGRATIONS = [IntegrationProvider.Audiobookshelf];
const YANK_INTEGRATIONS = [
IntegrationProvider.Audiobookshelf,
IntegrationProvider.Komga,
];
const PUSH_INTEGRATIONS = [
IntegrationProvider.Radarr,
IntegrationProvider.Sonarr,
Expand Down Expand Up @@ -154,6 +158,10 @@ const createSchema = z.object({
plexUsername: z.string().optional(),
audiobookshelfBaseUrl: z.string().optional(),
audiobookshelfToken: z.string().optional(),
komgaBaseUrl: z.string().optional(),
komgaUsername: z.string().optional(),
komgaPassword: z.string().optional(),
komgaProvider: z.nativeEnum(MediaSource).optional(),
radarrBaseUrl: z.string().optional(),
radarrApiKey: z.string().optional(),
radarrProfileId: z.number().optional(),
Expand Down Expand Up @@ -438,6 +446,34 @@ const CreateIntegrationModal = (props: {
/>
</>
))
.with(IntegrationProvider.Komga, () => (
<>
<TextInput
label="Base Url"
required
name="providerSpecifics.komgaBaseUrl"
/>
<TextInput
label="Username"
required
name="providerSpecifics.komgaUsername"
/>
<TextInput
label="Password"
required
name="providerSpecifics.komgaPassword"
/>
<Select
label="Select a provider"
name="providerSpecifics.komgaProvider"
required
data={[MediaSource.Anilist, MediaSource.Mal].map((is) => ({
label: changeCase(is),
value: is,
}))}
/>
</>
))
.with(IntegrationProvider.Plex, () => (
<>
<TextInput
Expand Down
1 change: 1 addition & 0 deletions crates/background/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ pub enum ApplicationJob {
RecalculateUserSummary(String),
PerformBackgroundTasks,
UpdateExerciseLibrary,
SyncIntegrationsData,
}

impl Message for ApplicationJob {
Expand Down
1 change: 1 addition & 0 deletions crates/enums/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,7 @@ pub enum IntegrationProvider {
Kodi,
Radarr,
Sonarr,
Komga,
}

#[derive(
Expand Down
2 changes: 1 addition & 1 deletion crates/migrations/src/m20230505_create_review.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use sea_orm_migration::prelude::*;
use enums::Visibility;
use sea_orm_migration::prelude::*;

use super::{
m20230410_create_metadata::Metadata, m20230413_create_person::Person,
Expand Down
6 changes: 5 additions & 1 deletion crates/models/media/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::{collections::HashSet, fmt, sync::Arc};

use async_graphql::{Enum, InputObject, InputType, OneofObject, SimpleObject, Union};
use boilermates::boilermates;
use chrono::{DateTime, NaiveDate,NaiveDateTime};
use chrono::{DateTime, NaiveDate, NaiveDateTime};
use common_models::{
CollectionExtraInformation, IdAndNamedObject, SearchInput, StoredUrl, StringIdObject,
};
Expand Down Expand Up @@ -911,6 +911,10 @@ pub struct IntegrationProviderSpecifics {
pub plex_username: Option<String>,
pub audiobookshelf_base_url: Option<String>,
pub audiobookshelf_token: Option<String>,
pub komga_base_url: Option<String>,
pub komga_username: Option<String>,
pub komga_password: Option<String>,
pub komga_provider: Option<MediaSource>,
pub radarr_base_url: Option<String>,
pub radarr_api_key: Option<String>,
pub radarr_profile_id: Option<i32>,
Expand Down
9 changes: 7 additions & 2 deletions crates/providers/src/manga_updates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,12 @@ struct MetadataSearchResponse<T> {
}

impl MangaUpdatesService {
fn extract_status(&self, input: &str) -> (Option<i32>, Option<String>) {
fn extract_status(&self, input: Option<String>) -> (Option<i32>, Option<String>) {
if input.is_none() {
return (None, None);
}

let input = input.unwrap();
let first_part = input.split("<BR>").next().unwrap_or("").trim();
let parts: Vec<&str> = first_part.split_whitespace().collect();

Expand Down Expand Up @@ -324,7 +329,7 @@ impl MediaProvider for MangaUpdatesService {
}
}

let (volumes, status) = self.extract_status(&data.status.clone().unwrap());
let (volumes, status) = self.extract_status(data.status.clone());

Ok(MediaDetails {
identifier: data.series_id.unwrap().to_string(),
Expand Down
2 changes: 2 additions & 0 deletions crates/services/integration/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ anyhow = { workspace = true }
application-utils = { path = "../../utils/application" }
async-graphql = { workspace = true }
enums = { path = "../../enums" }
eventsource-stream = "=0.2.3"
database-models = { path = "../../models/database" }
database-utils = { path = "../../utils/database" }
media-models = { path = "../../models/media" }
Expand All @@ -23,5 +24,6 @@ serde = { workspace = true }
serde_json = { workspace = true }
sonarr-api-rs = "=3.0.0"
specific-models = { path = "../../models/specific" }
tokio = "1.39.2"
tracing = { workspace = true }
traits = { path = "../../traits" }
Loading