Skip to content

Commit

Permalink
temp
Browse files Browse the repository at this point in the history
  • Loading branch information
dittos committed Feb 29, 2020
1 parent dad57da commit 33ebae2
Show file tree
Hide file tree
Showing 33 changed files with 868 additions and 482 deletions.
2 changes: 0 additions & 2 deletions backend/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ dependencies {
compile "org.postgresql:postgresql"
compile "org.liquibase:liquibase-core"
compile "org.jsoup:jsoup:1.11.3"
compile 'org.jetbrains.exposed:exposed:0.11.2'
compile 'org.jetbrains.exposed:spring-transaction:0.11.2'
compile 'org.twitter4j:twitter4j-core:4.0.7'
testCompile "org.springframework.boot:spring-boot-starter-test"
testCompile "ru.yandex.qatools.embed:postgresql-embedded:2.9"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import net.animeta.backend.serializer.PostSerializer
import net.animeta.backend.serializer.RecordSerializer
import net.animeta.backend.serializer.UserSerializer
import org.apache.tomcat.util.http.LegacyCookieProcessor
import org.jetbrains.exposed.sql.Database
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.autoconfigure.SpringBootApplication
Expand All @@ -28,7 +27,6 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor
import org.springframework.stereotype.Component
import org.springframework.web.method.support.HandlerMethodArgumentResolver
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
import javax.sql.DataSource

fun main(args: Array<String>) {
runApplication<Application>(*args)
Expand All @@ -37,11 +35,6 @@ fun main(args: Array<String>) {
@SpringBootApplication
@PropertySource("classpath:/common.properties")
class Application {
@Bean
fun database(dataSource: DataSource): Database {
return Database.connect(dataSource)
}

@Bean
@Primary
fun objectMapper(builder: Jackson2ObjectMapperBuilder): ObjectMapper {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,21 @@ import net.animeta.backend.exception.ApiException
import net.animeta.backend.metadata.WorkMetadata
import net.animeta.backend.model.Company
import net.animeta.backend.model.Person
import net.animeta.backend.model.QUser.user
import net.animeta.backend.model.QWork.work
import net.animeta.backend.model.TitleMapping
import net.animeta.backend.model.User
import net.animeta.backend.repository.CompanyRepository
import net.animeta.backend.repository.HistoryRepository
import net.animeta.backend.repository.PersonRepository
import net.animeta.backend.repository.RecordRepository
import net.animeta.backend.repository.TitleMappingRepository
import net.animeta.backend.repository.WorkCastRepository
import net.animeta.backend.repository.WorkIndexRepository
import net.animeta.backend.repository.WorkRepository
import net.animeta.backend.repository.WorkStaffRepository
import net.animeta.backend.repository.WorkTitleIndexRepository
import net.animeta.backend.security.CurrentUser
import net.animeta.backend.serializer.WorkSerializer
import net.animeta.backend.service.ChartService
import net.animeta.backend.service.CompanyMutations
import net.animeta.backend.service.WorkMutations
import net.animeta.backend.service.WorkService
import net.animeta.backend.service.admin.AnnMetadataCache
import net.animeta.backend.service.admin.AnnService
Expand All @@ -49,25 +47,27 @@ import java.util.UUID

@RestController
@RequestMapping("/admin")
class AdminController(private val datastore: Datastore,
private val workService: WorkService,
private val imageService: ImageService,
private val workRepository: WorkRepository,
private val workIndexRepository: WorkIndexRepository,
private val workTitleIndexRepository: WorkTitleIndexRepository,
private val recordRepository: RecordRepository,
private val titleMappingRepository: TitleMappingRepository,
private val historyRepository: HistoryRepository,
private val chartService: ChartService,
private val workStaffRepository: WorkStaffRepository,
private val workCastRepository: WorkCastRepository,
private val personRepository: PersonRepository,
private val companyRepository: CompanyRepository,
private val workSerializer: WorkSerializer,
private val tablePeriodController: TablePeriodController,
private val annService: AnnService,
private val annMetadataCache: AnnMetadataCache,
private val objectMapper: ObjectMapper) {
class AdminController(
private val datastore: Datastore,
private val workService: WorkService,
private val workMutations: WorkMutations,
private val imageService: ImageService,
private val workRepository: WorkRepository,
private val workIndexRepository: WorkIndexRepository,
private val recordRepository: RecordRepository,
private val titleMappingRepository: TitleMappingRepository,
private val chartService: ChartService,
private val workStaffRepository: WorkStaffRepository,
private val workCastRepository: WorkCastRepository,
private val personRepository: PersonRepository,
private val companyRepository: CompanyRepository,
private val companyMutations: CompanyMutations,
private val workSerializer: WorkSerializer,
private val tablePeriodController: TablePeriodController,
private val annService: AnnService,
private val annMetadataCache: AnnMetadataCache,
private val objectMapper: ObjectMapper
) {
@GetMapping("/works")
fun getWorks(@CurrentUser currentUser: User,
@RequestParam("orphans", defaultValue = "false") onlyOrphans: Boolean,
Expand All @@ -88,7 +88,7 @@ class AdminController(private val datastore: Datastore,
fun createWork(@CurrentUser currentUser: User,
@RequestBody request: CreateWorkRequest): WorkDTO {
checkPermission(currentUser)
val work = workService.getOrCreate(request.title)
val work = workMutations.getOrCreate(request.title)
return workSerializer.serialize(work)
}

Expand Down Expand Up @@ -169,78 +169,37 @@ class AdminController(private val datastore: Datastore,
@RequestBody request: EditWorkRequest): AdminWorkDTO {
checkPermission(currentUser)
if (request.primaryTitleMappingId != null) {
setPrimaryTitleMapping(request.primaryTitleMappingId)
val work = workRepository.findById(id).get()
workMutations.updatePrimaryTitleMapping(work, request.primaryTitleMappingId)
}
if (request.mergeWorkId != null) {
mergeWork(id, request.mergeWorkId, request.forceMerge ?: false)
val work = workRepository.findById(id).get()
val other = workRepository.findById(request.mergeWorkId).get()
workMutations.merge(work, other, force = request.forceMerge ?: false)
}
if (request.rawMetadata != null) {
editMetadata(id, request.rawMetadata)
val work = workRepository.findById(id).orElse(null)
workMutations.updateMetadata(work, workService.parseMetadata(request.rawMetadata))
}
if (request.crawlImage != null) {
crawlImage(id, request.crawlImage)
}
if (request.blacklisted != null) {
val work = workRepository.findById(id).orElse(null)
work.blacklisted = request.blacklisted
workRepository.save(work)
workMutations.blacklist(work)
}
if (request.imageCenterY != null) {
val work = workRepository.findById(id).orElse(null)
work.image_center_y = request.imageCenterY
workRepository.save(work)
workMutations.updateImageCenter(work, request.imageCenterY)
}
if (request.importAnnMetadata != null) {
val work = workRepository.findById(id).orElse(null)
annService.importMetadata(work, annMetadataCache.getMetadata(request.importAnnMetadata))
workRepository.save(work)
workRepository.save(work) // FIXME
}
return getWork(currentUser, id)
}

private fun setPrimaryTitleMapping(primaryTitleMappingId: Int) {
val mapping = titleMappingRepository.findById(primaryTitleMappingId).orElse(null)
mapping.work.title = mapping.title
workRepository.save(mapping.work)
}

data class MergeError(val conflicts: List<MergeConflictDTO>)
data class MergeConflictDTO(val user_id: Int, val username: String, val ids: List<Int>)

private fun mergeWork(workId: Int, otherWorkId: Int, force: Boolean) {
val work = workRepository.findById(workId).orElse(null)
val other = workRepository.findById(otherWorkId).orElse(null)
if (work.id == other.id) {
throw ApiException("Cannot merge itself", HttpStatus.BAD_REQUEST)
}
val conflicts = datastore.query(user.query.filter(user.records.any().workId.eq(work.id!!)
.and(user.records.any().workId.eq(other.id!!))))
if (conflicts.isNotEmpty() && !force) {
throw ApiException("Users with conflict exist", HttpStatus.UNPROCESSABLE_ENTITY,
MergeError(conflicts = conflicts.map { MergeConflictDTO(
user_id = it.id!!,
username = it.username,
ids = it.records.filter { it.workId == work.id || it.workId == other.id }.map { it.id!! }
) }))
}
for (u in conflicts) {
historyRepository.deleteByUserAndWorkId(u, other.id!!)
recordRepository.deleteByUserAndWorkId(u, other.id!!)
}
titleMappingRepository.replaceWork(other, work)
historyRepository.replaceWorkId(other.id!!, work.id!!)
recordRepository.replaceWorkId(other.id!!, work.id!!)
workTitleIndexRepository.deleteAllByWork(other)
workIndexRepository.deleteById(other.id!!)
workRepository.delete(other)
}

@Transactional
fun editMetadata(id: Int, rawMetadata: String) {
val work = workRepository.findById(id).orElse(null)
workService.editMetadata(work, rawMetadata)
}

private fun crawlImage(id: Int, options: CrawlImageOptions) {
val work = workRepository.findById(id).orElse(null)
val tempFile = File.createTempFile("orig", ".tmp")
Expand All @@ -250,20 +209,20 @@ class AdminController(private val datastore: Datastore,
"ann" -> {
imageService.downloadAnnPoster(options.annId!!, tempFile)
imageService.generateThumbnail(tempFile, tempThumbFile)
work.original_image_filename = "ann${options.annId}.jpg"
work.image_filename = "thumb/v2/${work.original_image_filename}"
imageService.upload(tempFile, work.original_image_filename!!)
imageService.upload(tempThumbFile, work.image_filename!!)
workRepository.save(work)
val originalFilename = "ann${options.annId}.jpg"
val filename = "thumb/v2/${originalFilename}"
imageService.upload(tempFile, originalFilename)
imageService.upload(tempThumbFile, filename)
workMutations.updateImageFilename(work, filename, originalFilename)
}
"url" -> {
imageService.download(options.url!!, tempFile)
imageService.generateThumbnail(tempFile, tempThumbFile)
work.original_image_filename = UUID.randomUUID().toString()
work.image_filename = "thumb/${work.original_image_filename}"
imageService.upload(tempFile, work.original_image_filename!!)
imageService.upload(tempThumbFile, work.image_filename!!)
workRepository.save(work)
val originalFilename = UUID.randomUUID().toString()
val filename = "thumb/${work.original_image_filename}"
imageService.upload(tempFile, originalFilename)
imageService.upload(tempThumbFile, filename)
workMutations.updateImageFilename(work, filename, originalFilename)
}
}
} finally {
Expand All @@ -280,10 +239,7 @@ class AdminController(private val datastore: Datastore,
@PathVariable id: Int): DeleteResponse {
checkPermission(currentUser)
val work = workRepository.findById(id).orElse(null)
if (recordRepository.countByWorkId(work.id!!) != 0) {
throw ApiException("Record exists", HttpStatus.FORBIDDEN)
}
workRepository.delete(work)
workMutations.delete(work)
return DeleteResponse(true)
}

Expand All @@ -297,23 +253,15 @@ class AdminController(private val datastore: Datastore,
checkPermission(currentUser)
val work = workRepository.findById(id).orElse(null)
val title = request.title.trim()
val key = WorkService.normalizeTitle(title)
if (titleMappingRepository.countByKeyAndWorkIsNot(key, work) > 0) {
throw ApiException("Title already mapped", HttpStatus.FORBIDDEN)
}
val mapping = TitleMapping(work = work, title = title, key = key)
titleMappingRepository.save(mapping)
val mapping = workMutations.addTitleMapping(work, title)
return TitleMappingDTO(id = mapping.id!!, title = title, record_count = 0)
}

@DeleteMapping("/title-mappings/{id}")
fun deleteTitleMapping(@CurrentUser currentUser: User, @PathVariable id: Int): DeleteResponse {
checkPermission(currentUser)
val mapping = titleMappingRepository.findById(id).orElse(null)
if (recordRepository.countByTitle(mapping.title) > 0) {
throw ApiException("Record exists", HttpStatus.FORBIDDEN)
}
titleMappingRepository.delete(mapping)
val titleMapping = titleMappingRepository.findById(id).orElse(null)
workMutations.deleteTitleMapping(titleMapping)
return DeleteResponse(true)
}

Expand Down Expand Up @@ -412,51 +360,16 @@ class AdminController(private val datastore: Datastore,
fun editCompany(@CurrentUser currentUser: User, @PathVariable id: Int, @RequestBody request: EditCompanyRequest): CompanyDTO {
checkPermission(currentUser)
val company = companyRepository.findById(id).get()
if (request.name != null && company.name != request.name) {
if (companyRepository.findOneByName(request.name) != null) {
throw Exception("Name collision")
}
val prevName = company.name
company.name = request.name
companyRepository.save(company)

for (workCompany in company.works) {
val work = workCompany.work
val metadata = work.metadata?.let { objectMapper.readValue<WorkMetadata>(it) } ?: WorkMetadata()
workService.editMetadata(work, metadata.copy(
studios = metadata.studios?.map {
if (it == prevName) company.name else it
}
))
}
if (request.name != null) {
companyMutations.updateName(company, request.name)
}
if (request.mergeCompanyId != null) {
mergeCompany(id, request.mergeCompanyId)
val other = companyRepository.findById(request.mergeCompanyId).get()
companyMutations.merge(company, other)
}
return getCompany(id)
}

private fun mergeCompany(companyId: Int, otherCompanyId: Int) {
val company = companyRepository.findById(companyId).get()
val other = companyRepository.findById(otherCompanyId).get()
if (company.id == other.id) {
throw ApiException("Cannot merge itself", HttpStatus.BAD_REQUEST)
}
if (other.works.any { it.company.id == company.id }) {
throw ApiException("Works with conflict exists", HttpStatus.BAD_REQUEST)
}
for (workCompany in other.works) {
val work = workCompany.work
val metadata = work.metadata?.let { objectMapper.readValue<WorkMetadata>(it) } ?: WorkMetadata()
workService.editMetadata(work, metadata.copy(
studios = metadata.studios?.map {
if (it == other.name) company.name else it
}
))
}
companyRepository.delete(other)
}

private fun checkPermission(user: User) {
if (!user.staff) {
throw ApiException("Staff permission required.", HttpStatus.UNAUTHORIZED)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,9 @@ import net.animeta.backend.dto.PostDTO
import net.animeta.backend.exception.ApiException
import net.animeta.backend.model.QHistory.history
import net.animeta.backend.model.StatusType
import net.animeta.backend.repository.HistoryRepository
import net.animeta.backend.repository.WorkRepository
import net.animeta.backend.serializer.PostSerializer
import net.animeta.backend.sql.Histories
import org.jetbrains.exposed.sql.Database
import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.countDistinct
import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.transactions.transaction
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestMapping
Expand All @@ -23,8 +18,8 @@ import org.springframework.web.bind.annotation.RestController
@RestController
@RequestMapping("/v2/works/{id:[0-9]+}/posts")
class WorkPostsController(val workRepository: WorkRepository,
val historyRepository: HistoryRepository,
val datastore: Datastore,
val database: Database,
val postSerializer: PostSerializer) {
data class GetWithCountsResponse(val data: List<PostDTO>, val userCount: Int?, val suspendedUserCount: Int?)

Expand Down Expand Up @@ -53,17 +48,11 @@ class WorkPostsController(val workRepository: WorkRepository,
}

val (userCount, suspendedUserCount) = if (episode != null) {
transaction(database) {
val counts = Histories.slice(Histories.statusType, Histories.userId.countDistinct())
.select { Histories.workId.eq(work.id!!).and(Histories.status.eq(episode)) }
.groupBy(Histories.statusType)
.toList()
Pair(
counts.sumBy { it[Histories.userId.countDistinct()] },
counts.find { it[Histories.statusType] == StatusType.SUSPENDED.ordinal }
?.let { it[Histories.userId.countDistinct()] } ?: 0
)
}
val counts = historyRepository.countDistinctUsersByStatusType(work.id!!, episode)
Pair(
counts.sumBy { it.second.toInt() },
counts.find { it.first == StatusType.SUSPENDED }?.second?.toInt() ?: 0
)
} else {
Pair(null, null) // TODO
}
Expand Down
Loading

0 comments on commit 33ebae2

Please sign in to comment.