Skip to content

Commit

Permalink
Experiment with User data
Browse files Browse the repository at this point in the history
  • Loading branch information
orchestr7 committed Sep 8, 2024
1 parent 310ecb9 commit 7090812
Show file tree
Hide file tree
Showing 23 changed files with 802 additions and 238 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
# Важно
Сделано за 3 ночи 1 человеком, который был и швец, и жнец, и на дуде игрец. И девопс, и бэкендер и фронтендер.
Спасибо ChatGpt и моей маме.

# Покемон Или BigData

Шутливое приложение, которое показывает, насколько огромный зоопарк из названий образовался в дате.
Оригинальная идея и отсылки к [этой форме](https://docs.google.com/a/octo.com/forms/d/1kckcq_uv8dk9-W5rIdtqRwCHN4Uh209ELPUjTEZJDxc/viewform) и к [этому](https://github.com/pixelastic/pokemonorbigdata) проекту.


### How to
1) Build: `./gradlew build`

Expand Down
1 change: 1 addition & 0 deletions backend/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.liquibase:liquibase-core")
implementation("com.h2database:h2:2.3.232")
implementation("commons-codec:commons-codec:1.17.1")
runtimeOnly("io.jsonwebtoken:jjwt-impl:0.11.5")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,49 +3,13 @@ package ru.posidata.backend.controller
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*
import ru.posidata.backend.service.TelegramAuthService


@RestController
@RequestMapping("api")
class TelegramAuthController(private val telegramAuthService: TelegramAuthService) {
// <!DOCTYPE html>
//<html lang="en">
//<head>
// <meta charset="UTF-8">
// <meta name="viewport" content="width=device-width, initial-scale=1.0">
// <title>Telegram Login</title>
// <style>
// body {
// font-family: Arial, sans-serif;
// margin: 0;
// padding: 0;
// display: flex;
// justify-content: center;
// align-items: center;
// height: 100vh;
// background-color: #f4f4f4;
// }
// .container {
// text-align: center;
// }
// h1 {
// margin-bottom: 24px;
// }
// </style>
//</head>
//<body>
//<div class="container">
// <h1>Login with Telegram</h1>
// <p>Click the button below to log in using your Telegram account:</p>
// <script async src="https://telegram.org/js/telegram-widget.js?22" data-telegram-login="PosiDataBot" data-size="large" data-auth-url="https://posidata.ru/api/test" data-request-access="write"></script>
//</div>
//</body>
//</html>
// https://posidata.ru/api/test?id=221298772&first_name=Андрей&last_name=Кулешов&username=akuleshov7&photo_url=https%3A%2F%2Ft.me%2Fi%2Fuserpic%2F320%2Fd3fKyG306aXHDBCxZXfWTpGlii6fZqZMo1tBmMPEl_E.jpg&auth_date=1725656645&hash=742dda3a019e57821e1fb7acf9918aeb6f0d734cc5c8612913b6696aeab2c745
@GetMapping("/get")
fun get(): String {
class TestController {
@GetMapping("/test")
fun get(): ResponseEntity<Any> {
println("Hi!")
return "Hi"
return ResponseEntity.status(HttpStatus.OK).body("HI!")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import ru.posidata.backend.service.TelegramAuthService
import ru.posidata.backend.service.UserService
import ru.posidata.common.ResourceType
import ru.posidata.common.Resources
import ru.posidata.common.UserDataFromTelegram


@RestController
Expand All @@ -17,41 +18,62 @@ class UserController(
) {
@GetMapping("/get")
fun getResults(
@RequestParam username: String?,
@RequestParam telegramId: Long,
@RequestParam authDate: Int,
@RequestParam firstName: String,
@RequestParam lastName: String,
@RequestParam hash: String,
@RequestParam firstName: String?,
@RequestParam lastName: String?,
@RequestParam id: Int,
@RequestParam photoUrl: String,
@RequestParam username: String,
): ResponseEntity<Any> {
println("Received a request to get results from $username, $telegramId, $hash, $firstName, $lastName")
userService.findOrCreateUser(
username = username,
telegramId = telegramId,
val user = UserDataFromTelegram(
authDate = authDate,
firstName = firstName,
lastName = lastName
lastName = lastName,
hash = hash,
id = id,
photoUrl = photoUrl,
username = username,
)
return ResponseEntity.status(HttpStatus.OK).body("")
println("Received a request to get results from $user. Converted to map: ${user.convertToMap()}")

if(!telegramAuthService.isValidHash(user.convertToMap(), user.hash)) {
return ResponseEntity(HttpStatus.FORBIDDEN)
}

println("Validation successful for ${user.username}")

val responseUser = userService.findOrCreateUser(user)
return ResponseEntity.status(HttpStatus.OK).body(responseUser.toDTO())
}

@GetMapping("/answer")
@GetMapping("/update")
fun submitAnswer(
@RequestParam pokemonName: String,
@RequestParam resourceType: ResourceType,
// @RequestParam gameNumber: Int,
@RequestParam username: String,
@RequestParam authDate: Int,
@RequestParam firstName: String,
@RequestParam lastName: String,
@RequestParam hash: String,
@RequestParam id: Int,
@RequestParam photoUrl: String,
@RequestParam username: String,
@RequestParam isNextRound: Boolean
): ResponseEntity<Any> {
// user
println(pokemonName)
var count: Int = 0
val pokemon = Resources.getByName(pokemonName)
?: return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Invalid pokemon name $pokemonName")
if (pokemon.type == resourceType) {
// correct answer
++count
} else {
// incorrect answer
val user = UserDataFromTelegram(
authDate = authDate,
firstName = firstName,
lastName = lastName,
hash = hash,
id = id,
photoUrl = photoUrl,
username = username,
)
println("Received a request to get results from $user. Converted to map: ${user.convertToMap()}")

if(!telegramAuthService.isValidHash(user.convertToMap(), user.hash)) {
return ResponseEntity(HttpStatus.FORBIDDEN)
}
return ResponseEntity.status(HttpStatus.OK).body(resourceType)

val responseUser = userService.updateGameRound(user.username, isNextRound)
return ResponseEntity.status(HttpStatus.OK).body(responseUser?.toDTO())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package ru.posidata.backend.entity

import jakarta.persistence.*
import ru.posidata.common.UserForSerializationDTO

@Entity
@Table(name = "users")
class OurUserEntityFromDb(
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long = 0,
var firstName: String?,
var lastName: String?,
var username: String?,

var firstGameScore: Int,
var secondGameScore: Int,
var thirdGameScore: Int,
) {
fun toDTO(): UserForSerializationDTO {
return UserForSerializationDTO(
firstName = this.firstName,
lastName = this.lastName,
username = this.username,
firstGameScore = this.firstGameScore,
secondGameScore = this.secondGameScore,
thirdGameScore = this.thirdGameScore
)
}

fun currentGameNumber() =
when {
firstGameScore == -1 -> 1
secondGameScore == -1 && firstGameScore != -1 -> 2
thirdGameScore == -1 && firstGameScore != -1 && secondGameScore != -1 -> 3
else -> 4
}

fun updateResultIn(currentGameNumber: Int, isNextRound: Boolean) {
when(currentGameNumber) {
1 -> if(!isNextRound) ++firstGameScore else ++secondGameScore
2 -> if(!isNextRound) ++secondGameScore else ++thirdGameScore
3 -> if(!isNextRound) ++thirdGameScore
}
println(firstGameScore)
println(secondGameScore)
println(thirdGameScore)
}

override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false

other as OurUserEntityFromDb

if (id != other.id) return false
if (firstName != other.firstName) return false
if (lastName != other.lastName) return false
if (username != other.username) return false
if (firstGameScore != other.firstGameScore) return false
if (secondGameScore != other.secondGameScore) return false
if (thirdGameScore != other.thirdGameScore) return false

return true
}

override fun hashCode(): Int {
var result = id.hashCode()
result = 31 * result + (firstName?.hashCode() ?: 0)
result = 31 * result + (lastName?.hashCode() ?: 0)
result = 31 * result + (username?.hashCode() ?: 0)
result = 31 * result + (firstGameScore?.hashCode() ?: 0)
result = 31 * result + (secondGameScore?.hashCode() ?: 0)
result = 31 * result + (thirdGameScore?.hashCode() ?: 0)
return result
}
}
24 changes: 0 additions & 24 deletions backend/src/main/kotlin/ru/posidata/backend/entity/User.kt

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ package ru.posidata.backend.repository

import org.springframework.data.repository.CrudRepository
import org.springframework.stereotype.Repository
import ru.posidata.backend.entity.User
import ru.posidata.backend.entity.OurUserEntityFromDb

@Repository
interface UserRepository : CrudRepository<User, Long> {
fun findByTelegramId(telegramId: Long): User?
interface UserRepository : CrudRepository<OurUserEntityFromDb, Long> {
fun findByUsername(username: String): OurUserEntityFromDb?
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,56 +3,21 @@ package ru.posidata.backend.service
import org.apache.commons.codec.digest.HmacUtils
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Service
import java.security.MessageDigest


@Service
class TelegramAuthService(
@Value("\${telegram.bot.token}") private val telegramToken: String,
) {
fun isValidHash(hash: String): Boolean {
val secreteKey = "1289756607:AAFYuBeHguJKYhDVzwSfYFLX4tF5YbkSU7M"
return true
}

}
/*
fun main() {
println(isValidHash())
}
// Bot token
const val BOT_TOKEN = "7518590686:AAFCT7m70_ANfOZfIACr2C7bOy0igdLNOpg"
fun isValidHash(parsedData: Map<String, String>, hash: String): Boolean {
val dataKeys = parsedData.keys.filter { it != "hash" }.sorted()
val items = dataKeys.map { key -> "$key=${parsedData[key]}" }
val dataCheckString = items.joinToString("\n")

// Function to validate hash
fun isValidHash(): Boolean {
val hash = "742dda3a019e57821e1fb7acf9918aeb6f0d734cc5c8612913b6696aeab2c745"
val secretKey: ByteArray = MessageDigest.getInstance("SHA-256").digest(telegramToken.toByteArray())
val initDataHash: String = HmacUtils("HmacSHA256", secretKey).hmacHex(dataCheckString)

val parsedData: Map<String, String> = mapOf(
"id" to "221298772",
"first_name" to "Андрей",
"last_name" to "Кулешов",
"username" to "akuleshov7",
"photo_url" to "https%3A%2F%2Ft.me%2Fi%2Fuserpic%2F320%2Fd3fKyG306aXHDBCxZXfWTpGlii6fZqZMo1tBmMPEl_E.jpg",
"auth_date" to "1725656645",
"hash" to "742dda3a019e57821e1fb7acf9918aeb6f0d734cc5c8612913b6696aeab2c745"
)
// Remove 'hash' value & sort alphabetically
val dataKeys = parsedData.keys.filter { it != "hash" }.sorted()
// Create line format key=<value>
val items = dataKeys.map { key -> "$key=${parsedData[key]}" }
// Create check string with '\n' as separator
val dataCheckString = items.joinToString("\n")
val secretKey: ByteArray = HmacUtils("HmacSHA256", "WebAppData").hmac(BOT_TOKEN)
val initDataHash: String = HmacUtils("HmacSHA256", secretKey).hmacHex(dataCheckString)
println(initDataHash)
println(hash)
// Return whether the generated hash matches the provided hash
return initDataHash == hash
return initDataHash == hash
}
}
*/
Loading

0 comments on commit 7090812

Please sign in to comment.