├── api_doc.md ├── doc ├── apiserver ├── config.ini ├── gotye_open_live.sql ├── gotyelive_server.tar.gz └── run ├── install ├── pic ├── freamwork.jpg ├── gotyelive-group01.png └── gotyelive1.0.png ├── readme.md ├── server.md └── src ├── apiserver ├── config.ini ├── liveapi │ ├── authCode.go │ ├── createLiveRoom.go │ ├── followLiveRoom.go │ ├── getLiveRoomList.go │ ├── getLiveroomNumber.go │ ├── getMyLiveRoom.go │ ├── getMyLiveRoomId.go │ ├── getUserHeadPic.go │ ├── login.go │ ├── modifyMyLiveRoom.go │ ├── modifyUserHeadPic.go │ ├── modifyUserInfo.go │ ├── modifyUserPwd.go │ ├── payApi.go │ ├── playLiveStream.go │ ├── pushLiveStream.go │ ├── refreshPlayUrls.go │ ├── register.go │ ├── router.go │ └── searchLiveRoom.go ├── main.go └── service │ ├── authCode.go │ ├── dbInit.go │ ├── dbLiveRoom.go │ ├── dbUser.go │ ├── gotyeRequestApi.go │ ├── gotyeRequestApi_test.go │ ├── liveroom.go │ ├── liveroomList.go │ ├── liveroomSearch.go │ ├── onlineLiveManager.go │ ├── payManager.go │ ├── payManager_test.go │ ├── refreshPlayUrls.go │ ├── sessionManager.go │ └── user.go └── gotye_protocol ├── api.go ├── api_doc.md ├── base.go ├── gotye_sdk ├── api.go └── status_code.go └── status_code.go /api_doc.md: -------------------------------------------------------------------------------- 1 | #GotyeLive Server API 文档(app应用层协议) 2 | 3 | ##返回码列表 4 | 5 | ###请求相关 6 | 7 | |返回码 |描述 |值 |备注 | 8 | |-------------------------|-------------------|-----|------------| 9 | |API_SUCCESS |"成功" |10000|请求成功 | 10 | |API_SERVER_ERROR |"系统异常" |10001|几乎不会发生| 11 | |API_PARAM_ERROR |"参数错误" |10002|几乎不会发生| 12 | |API_EXPIRED_SESSION_ERROR|"登录过期,重新登录"|10003|离最后一次访问服务器超过一个小时过期| 13 | 14 | ###回复相关 15 | 16 | ####a. 账号相关 17 | 18 | |返回码 |描述 |值 |备注 | 19 | |----------------------------|--------------|-----|----------| 20 | |API_USERNAME_NOT_EXISTS_ERROR|"用户名不存在" |10100|登录时 | 21 | |API_USERNAME_EXISTS_ERROR |"用户名已使用" |10101|注册时 | 22 | |API_LOGIN_PASSWORD_ERROR |"登录密码错误"|10102|登录时 | 23 | |API_PHONE_EXISTS_ERROR |"手机已注册" |10103|注册时 | 24 | |API_PHONE_NOT_EXISTS_ERROR |"手机不存在" |10104|修改密码时| 25 | |API_AUTHCODE_ERROR |"验证码错误" |10105|注册or找回密码时| 26 | 27 | ####b. 直播室相关 28 | 29 | |返回码 |描述 |值 |备注 | 30 | |-----------------------------------|----------------|-----|-------------------| 31 | |API_LIVEROOM_ID_NOT_EXIST_ERROR |"直播室ID不存在"|10200|推流,修改,搜索时 | 32 | |API_REPECT_PASSWORD_LIVEROOM_ERROR |"直播室密码重复"|10201|修改直播室,不会发生| 33 | |API_LIVEROOM_NOT_EXISTS_ERROR |"直播室不存在" |10202|获取自己聊天室时 | 34 | |API_INVALID_LIVEROOM_NAME_ERROR |"直播室名称非法"|10203|修改直播室时 | 35 | |API_INVALID_PASSWORD_LIVEROOM_ERROR|"直播室密码非法"|10204|一般不会发生 | 36 | 37 | ####c. 图片相关 38 | 39 | |返回码 |描述 |值 |备注 | 40 | |-------------------------|--------------|-----|-----------------------------| 41 | |API_DECODE_HEAD_PIC_ERROR|"头像解码错误"|10300|base64解压头像时,一般不会发生| 42 | 43 | ####d. 支付相关 44 | |返回码 |描述 |值 |备注 | 45 | |-------------------------|--------------|-----|------------| 46 | |API_CHARGE_RMB_ERROR |"支付系统异常"|10400|充值人民币时| 47 | |API_LACK_OF_BALANCE_ERROR|"账户余额不足"|10401|送礼物时 | 48 | 49 | 50 | 51 | ##请求回复说明 52 | 53 | 所有的API,请求返回头部格式的内容: 54 | 55 | ``` 56 | { 57 | "access" : 58 | "status" : <状态码> 59 | "desc" : <描述> 60 | } 61 | ``` 62 | 63 | 例如: 64 | 65 | ``` 66 | { 67 | "access" : "live/Login" 68 | "status" : 10000, 69 | "desc" : "成功" 70 | } 71 | ``` 72 | 73 | ``` 74 | { 75 | "access" : "live/Register" 76 | "status" : 10102, 77 | "desc" : "账号已注册" 78 | } 79 | ``` 80 | 81 | ##API协议说明 82 | 83 | ###a. POST method API 84 | 85 | ``` 86 | 用户登录API : /live/Login 87 | 88 | request 89 | { 90 | "account" : 账号/手机号/邮箱 91 | "password": "123456" 92 | } 93 | 94 | response 95 | { 96 | "access" : "/live/Login" 97 | "status" : 98 | "desc" : 99 | "nickName" : "aaaaaa" 100 | "liveRoomId" : 如果这个用户有liveRoomId,就返回,如果没有返回0 101 | "sessionId" : (32个字节的字符串) 102 | "headPicId" : 头像ID 103 | "sex" : 1 男,2 女 104 | } 105 | ``` 106 | 107 | ``` 108 | 获取验证码API : /live/AuthCode 109 | request 110 | { 111 | "phone" : "13512023289", 112 | } 113 | 114 | response 115 | { 116 | "access" : "/live/AuthCode" 117 | "status" : 118 | "desc" : 119 | } 120 | ``` 121 | 122 | ``` 123 | 用户注册API : /live/Register 124 | 125 | request 126 | { 127 | "phone" : "13512023289", 128 | "password" : "123456" 129 | "authCode" : "123456", 130 | } 131 | 132 | response 133 | { 134 | "access" : "/live/Register" 135 | "status" : 136 | "desc" : 137 | } 138 | ``` 139 | 140 | ``` 141 | 用户密码修改API : live/ModifyUserPwd 142 | 143 | request 144 | { 145 | "phone" : "", 146 | "password": "123456" 147 | } 148 | 149 | response 150 | { 151 | "access" : "/live/ModifyUserPwd" 152 | "status" : 153 | "desc" : 154 | } 155 | ``` 156 | 157 | ``` 158 | 用户个人信息修改API : /live/ModifyUserInfo 159 | 160 | request 161 | { 162 | "sessionId" : "" 163 | "nickName" : 如果不修改填"" 164 | "sex" : 如果不修改填0 165 | "address" : 如果不修改填"" 166 | } 167 | 168 | response 169 | { 170 | "access" : "/live/ModifyUserInfo" 171 | "status" : 172 | "desc" : 173 | } 174 | ``` 175 | 176 | ``` 177 | 用户头像修改API : /live/ModifyUserHeadPic 178 | 179 | request 180 | { 181 | "sessionId" : "asssssssssssssssssss" 182 | "headPic" : 修改用户头像 (图片base64之后成字符串再传入) 183 | } 184 | 185 | response 186 | { 187 | "access" : "/live/ModifyUserHeadPic" 188 | "status" : 189 | "desc" : 190 | "headPicId": 返回头像ID 191 | } 192 | ``` 193 | 194 | ``` 195 | 获取直播室列表API : /live/GetLiveRoomList 196 | 197 | request 198 | { 199 | "sessionId": 200 | "type" : 1(全部), 2(关注) 201 | "refresh" : 1(刷新), 0(获取下一页) 202 | "count" : 可以填充一次性刷新几个,如果不填,默认是5个 203 | } 204 | 205 | response(all) 206 | { 207 | "access" : "/live/GetLiveRoomList" 208 | "status" : 209 | "desc" : 210 | "type" : 1(全部) 211 | "list" : [ 212 | { 213 | "liveRoomId" : 214 | "liveRoomanchorPwd": 主播密码 215 | "liveRoomUserPwd": 观看直播的用户密码 216 | "liveRoomName" : 直播室名称 217 | "liveRoomDesc" : 直播室描述 218 | "liveRoomTopic": 演讲的题目 219 | "anchorName" : 主播昵称 220 | "headPicId" : 主播头像ID 221 | "isFollow" : 1 关注, 0 未关注 222 | "followCount" : 被关注量 223 | "playerCount" : 当前观看人数 224 | }, 225 | ] 226 | } 227 | 228 | response(fcous) 229 | { 230 | "access" : "/live/GetLiveRoomList" 231 | "status" : 232 | "desc" : 233 | "type" : 2(关注) 234 | "onlineList" : [ 当前正在直播的list 235 | { 236 | "liveRoomId" : 237 | "liveRoomanchorPwd": 主播密码 238 | "liveRoomUserPwd": 观看直播的用户密码 239 | "liveRoomName" : 直播室名称 240 | "liveRoomDesc" : 直播室描述 241 | "liveRoomTopic": 演讲的题目 242 | "anchorName" : 主播昵称 243 | "headPicId" : 主播头像ID 244 | "isFollow" : 1 关注, 0 未关注 245 | "followCount" : 被关注量 246 | "playerCount" : 当前观看人数 247 | }, 248 | ], 249 | "offlineList" : [ 当前未在直播的list 250 | { 251 | "liveRoomId" : 252 | "liveRoomanchorPwd": 主播密码 253 | "liveRoomUserPwd": 观看直播的用户密码 254 | "liveRoomName" : 直播室名称 255 | "liveRoomDesc" : 直播室描述 256 | "liveRoomTopic": 演讲的题目 257 | "anchorName" : 主播昵称 258 | "headPicId" : 主播头像ID 259 | "isFollow" : 1 关注, 0 未关注 260 | "followCount" : 被关注量 261 | "playerCount" : 当前观看人数 262 | }, 263 | ] 264 | } 265 | ``` 266 | 267 | ``` 268 | 获取用户自己直播室账号API : /live/GetMyLiveRoomId 269 | 270 | request 271 | { 272 | "sessionId" : "" 273 | } 274 | 275 | response 276 | { 277 | "access" : " /live/GetMyLiveRoomId" 278 | "status" : 279 | "desc" : 280 | "LiveRoomId": 1234567 281 | } 282 | ``` 283 | 284 | ``` 285 | 获取用户自己直播室API : /live/GetMyLiveRoom 286 | 287 | request 288 | { 289 | "sessionId" : "" 290 | } 291 | 292 | response 293 | { 294 | "access" : " /live/GetMyLiveRoom" 295 | "status" : 296 | "desc" : 297 | "liveRoomId" : 298 | "liveRoomanchorPwd": 主播密码 299 | "liveRoomUserPwd": 观看直播的用户密码 300 | "liveRoomName" : 直播室名称 301 | "liveRoomDesc" : 直播室描述 302 | "liveRoomTopic": 演讲的题目 303 | "anchorName" : 主播昵称 304 | "headPicId" : 主播头像ID 305 | "isFollow" : 1 关注, 0 未关注 306 | "followCount" : 被关注量 307 | "playerCount" : 当前观看人数 308 | } 309 | ``` 310 | 311 | ``` 312 | 修改用户自己直播室API : /live/ModifyMyLiveRoom 313 | 314 | request 315 | { 316 | "sessionId" : 317 | "liveRoomId" : 可为0, 318 | "liveRoomAnchorPwd" : 主播密码 319 | "liveRoomUserPwd" : 观看直播的用户密码 320 | "liveRoomName" : 直播室名称 321 | "liveRoomDesc" : 直播室描述 322 | "liveRoomTopic" : 直播的主题 323 | } 324 | 325 | response 326 | { 327 | "access" : " /live/ModifyMyLiveRoom" 328 | "status" : 329 | "desc" : 330 | } 331 | ``` 332 | 333 | ``` 334 | 创建直播室API : /live/CreateLiveRoom 335 | 336 | request 337 | { 338 | "sessionId" : 339 | "liveRoomAnchorPwd" : 主播密码 340 | "liveRoomAssistPwd" : 助理密码 341 | "liveRoomUserPwd" : 观看密码 342 | "liveRoomName" : 直播室名称 343 | "liveRoomDesc" : 直播室描述 344 | "liveRoomTopic" : 直播室主题 345 | 346 | } 347 | 348 | response 349 | { 350 | "access" : " /live/CreateLiveRoom" 351 | "status" : 352 | "desc" : 353 | "liveRoomId": 354 | } 355 | ``` 356 | 357 | ``` 358 | 关注和取消其他直播室API : /live/FollowLiveRoom 359 | 360 | request 361 | { 362 | "sessionId" : 363 | "liveRoomId" : 364 | "isFollow" : 1 关注, 0 取消 365 | 366 | } 367 | 368 | response 369 | { 370 | "access" : " /live/CreateLiveRoom" 371 | "status" : 372 | "desc" : 373 | } 374 | ``` 375 | 376 | ``` 377 | 开启和关闭直播API : /live/PushLiveStream 378 | 379 | request 380 | { 381 | "sessionId" : 382 | "liveRoomId" : 383 | "status" : 1 push, 0 stop 384 | "timeout" : 超时时间,默认60秒. 如果在此时间内没有设置状态为1,直播状态变为0 385 | } 386 | 387 | response 388 | { 389 | "access" : " /live/PushLiveStream" 390 | "status" : 391 | "desc" 392 | } 393 | ``` 394 | 395 | ``` 396 | 搜索直播室API : /live/SearchLiveStream 397 | 398 | request 399 | { 400 | "sessionId" : 401 | "keyword" : 目前只支持liveroomId 402 | } 403 | 404 | response 405 | { 406 | "access" : " /live/SearchLiveStream" 407 | "status" : 408 | "desc" : 409 | "liveRoomId" : 410 | "liveRoomanchorPwd": 主播密码 411 | "liveRoomUserPwd": 观看直播的用户密码 412 | "liveRoomName" : 直播室名称 413 | "liveRoomDesc" : 直播室描述 414 | "liveRoomTopic": 演讲的题目 415 | "anchorName" : 主播昵称 416 | "headPicId" : 主播头像ID 417 | "isFollow" : 1 关注, 0 未关注 418 | "followCount" : 被关注量 419 | "playerCount" : 当前观看人数 420 | "isPlay" : 1 直播, 0 已结束 421 | } 422 | ``` 423 | 424 | ``` 425 | 充值API: /pay/ChargeRMB 426 | 427 | request 428 | { 429 | "sessionId": 430 | "rmb" : 整型,最少1元,充值单位是元 431 | } 432 | 433 | response 434 | { 435 | "access" : "/pay/ChargeRMB" 436 | "status" : API_CHARGE_RMB_ERROR(10400) 437 | "desc" : 438 | "qinCoin" : 返回剩余多少亲元 439 | } 440 | ``` 441 | 442 | ``` 443 | 支付亲元API(送礼物): /pay/PayQinCoin 444 | 445 | request 446 | { 447 | "sessionId" : 448 | "qinCoin" : 支付亲元 449 | "anchorAccount" : 主播用户名 450 | } 451 | 452 | response 453 | { 454 | "access" : "/pay/PayQinCoin" 455 | "status" : API_LACK_OF_BALANCE_ERROR(10401) 账户余额不足 456 | "desc" : 457 | "qinCoin" : 返回剩余多少亲元 458 | } 459 | ``` 460 | 461 | ``` 462 | 获取自己账户信息API: /pay/GetPayAccount 463 | 464 | request 465 | { 466 | "sessionId" : 467 | } 468 | 469 | response 470 | { 471 | "access" : "/pay/GetPayAccount" 472 | "status" : 473 | "desc" : 474 | "qinCoin" : 剩余亲元 475 | "jiaCoin" : 收入加元 476 | "level" : 用户等级 477 | "xp" : 用户经验值 478 | } 479 | ``` 480 | 481 | ###b. GET method API 482 | 483 | ``` 484 | 获取用户头像API : /live/GetUserHeadPic 485 | 486 | request 487 | /live/GetUserHeadPic?id=headPicId 488 | 489 | response 490 | 如果成功,直接返回图片数据 491 | 492 | 如果失败,返回 493 | { 494 | "access": "/live/GetUserHeadPic", 495 | "status": 10002, 496 | "desc" : "参数错误" 497 | } 498 | ``` -------------------------------------------------------------------------------- /doc/apiserver: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QPlus/GotyeLive/54cfb1eaaff38e65c9a2e4875e83ca713e24c42b/doc/apiserver -------------------------------------------------------------------------------- /doc/config.ini: -------------------------------------------------------------------------------- 1 | [apiserver] 2 | http_port = 8080 3 | 4 | [mysql] 5 | address = 192.168.1.10 6 | dbname = gotye_open_live 7 | account = app 8 | password = 123456 9 | -------------------------------------------------------------------------------- /doc/gotye_open_live.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Source Server : 192.168.1.10 3 | Source Server Version : 50627 4 | Source Host : 192.168.1.10:3306 5 | Source Database : gotye_open_live 6 | 7 | Target Server Type : MYSQL 8 | Target Server Version : 50627 9 | File Encoding : 65001 10 | 11 | Date: 2016-04-07 15:29:41 12 | */ 13 | 14 | -- ---------------------------- 15 | -- Current Database: `gotye_open_live` 16 | -- ---------------------------- 17 | 18 | CREATE DATABASE `gotye_open_live`; 19 | 20 | USE `gotye_open_live`; 21 | 22 | 23 | -- ---------------------------- 24 | -- Table structure for tbl_app 25 | -- ---------------------------- 26 | DROP TABLE IF EXISTS `tbl_app`; 27 | CREATE TABLE `tbl_app` ( 28 | `id` int(11) NOT NULL AUTO_INCREMENT, 29 | `key` varchar(64) NOT NULL, 30 | `value` varchar(128) NOT NULL, 31 | PRIMARY KEY (`id`) 32 | ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; 33 | 34 | -- ---------------------------- 35 | -- Table structure for tbl_follow_liverooms 36 | -- ---------------------------- 37 | DROP TABLE IF EXISTS `tbl_follow_liverooms`; 38 | CREATE TABLE `tbl_follow_liverooms` ( 39 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 40 | `user_id` bigint(20) NOT NULL, 41 | `liveroom_id` bigint(20) NOT NULL, 42 | `follow_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 43 | PRIMARY KEY (`id`), 44 | UNIQUE KEY `index_user_liveroom_id` (`user_id`,`liveroom_id`) USING BTREE, 45 | KEY `index_user_id` (`user_id`) USING BTREE, 46 | KEY `index_liveroom_id` (`liveroom_id`) USING BTREE, 47 | CONSTRAINT `foreign_liveroom_id` FOREIGN KEY (`liveroom_id`) REFERENCES `tbl_liverooms` (`liveroom_id`) 48 | ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; 49 | 50 | -- ---------------------------- 51 | -- Table structure for tbl_liverooms 52 | -- ---------------------------- 53 | DROP TABLE IF EXISTS `tbl_liverooms`; 54 | CREATE TABLE `tbl_liverooms` ( 55 | `user_id` bigint(20) NOT NULL, 56 | `liveroom_id` bigint(20) NOT NULL, 57 | `liveroom_name` varchar(256) NOT NULL, 58 | `liveroom_desc` varchar(1024) DEFAULT NULL, 59 | `liveroom_topic` varchar(256) DEFAULT NULL, 60 | `anchor_pwd` varchar(64) NOT NULL, 61 | `assist_pwd` varchar(64) NOT NULL, 62 | `user_pwd` varchar(64) NOT NULL, 63 | `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 64 | PRIMARY KEY (`liveroom_id`), 65 | UNIQUE KEY `index_user_id` (`user_id`) USING BTREE, 66 | CONSTRAINT `foreign_user_id` FOREIGN KEY (`user_id`) REFERENCES `tbl_users` (`user_id`) 67 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 68 | 69 | -- ---------------------------- 70 | -- Table structure for tbl_online_liverooms 71 | -- ---------------------------- 72 | DROP TABLE IF EXISTS `tbl_online_liverooms`; 73 | CREATE TABLE `tbl_online_liverooms` ( 74 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 75 | `liveroom_id` bigint(20) NOT NULL, 76 | `pushing_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 77 | `player_num` int(11) NOT NULL DEFAULT '0' COMMENT '用户观看人数', 78 | PRIMARY KEY (`id`), 79 | UNIQUE KEY `index_liveroom_id` (`liveroom_id`) USING BTREE, 80 | UNIQUE KEY `index_id` (`id`) USING BTREE 81 | ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; 82 | 83 | -- ---------------------------- 84 | -- Table structure for tbl_pictures 85 | -- ---------------------------- 86 | DROP TABLE IF EXISTS `tbl_pictures`; 87 | CREATE TABLE `tbl_pictures` ( 88 | `pic_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '图片id', 89 | `pic` blob NOT NULL, 90 | PRIMARY KEY (`pic_id`), 91 | UNIQUE KEY `index_pic_id` (`pic_id`) USING BTREE 92 | ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; 93 | 94 | -- ---------------------------- 95 | -- Table structure for tbl_users 96 | -- ---------------------------- 97 | DROP TABLE IF EXISTS `tbl_users`; 98 | CREATE TABLE `tbl_users` ( 99 | `user_id` bigint(20) NOT NULL AUTO_INCREMENT, 100 | `account` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '唯一账号', 101 | `phone` varchar(20) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, 102 | `email` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, 103 | `nickname` varchar(64) NOT NULL, 104 | `pwd` varchar(32) NOT NULL, 105 | `headpic_id` bigint(20) NOT NULL DEFAULT '0', 106 | `sex` enum('male','female') NOT NULL DEFAULT 'male' COMMENT '性别,默认男', 107 | `address` varchar(128) NOT NULL DEFAULT '中国,上海', 108 | PRIMARY KEY (`user_id`), 109 | UNIQUE KEY `index_userid` (`user_id``) USING BTREE, 110 | UNIQUE KEY `index_account` (`account`) USING BTREE, 111 | UNIQUE KEY `index_phone` (`phone`) USING BTREE, 112 | UNIQUE KEY `index_email` (`email`) USING BTREE 113 | ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; 114 | -------------------------------------------------------------------------------- /doc/gotyelive_server.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QPlus/GotyeLive/54cfb1eaaff38e65c9a2e4875e83ca713e24c42b/doc/gotyelive_server.tar.gz -------------------------------------------------------------------------------- /doc/run: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | servername="./apiserver" 4 | 5 | param_1=$1 6 | 7 | #Function 8 | StartServer() 9 | { 10 | echo " >> start server" 11 | rm nohup.out -f 12 | echo "" >> nohup.out 13 | nohup $servername & > /dev/null 14 | 15 | echo " >> Start Success!!! " 16 | } 17 | 18 | StopServer() 19 | { 20 | echo " >> stop server" 21 | 22 | if [ $(GetPid ./apiserver) ] 23 | then 24 | echo " >> Stop $servername... PID="$(GetPid $servername) 25 | kill -9 $(GetPid $servername) 2> /dev/null 26 | fi 27 | 28 | echo " >> Stop Success!!! " 29 | } 30 | 31 | GetPid() 32 | { 33 | echo "`ps aux | grep $1 | grep -v grep | grep -v /bin/sh | awk '{if($2>0){print $2;}{exit}}'`" | tr " " "\n" 34 | } 35 | 36 | GetTime() 37 | { 38 | echo "`ps aux | grep $1 | grep -v grep | grep -v /bin/sh | awk '{print $9;}{exit}'`" 39 | } 40 | 41 | Info() 42 | { 43 | echo " ==========================================================================" 44 | printf " %-30s\t\t%-10s%-10s \n" [ServerName] [PID] [TIME] 45 | echo " --------------------------------------------------------------------------" 46 | pid=$( GetPid $servername ) 47 | tm=$( GetTime $servername ) 48 | printf " %-30s\t\t%-10s%-10s \n" $servername $pid $tm 49 | echo " ==========================================================================" 50 | } 51 | 52 | Help() 53 | { 54 | echo " ================== How To Use ==================" 55 | echo " run " 56 | echo " Command List:" 57 | echo " -s or start Start Server" 58 | echo " -k or stop Stop Server" 59 | echo " -i or info Show ServerInfo" 60 | echo " -h or help Get Some Info for the Script" 61 | } 62 | 63 | 64 | #Main 65 | case "$param_1" in 66 | "start"|"-s") 67 | StartServer;; 68 | 69 | "stop"|"-k") 70 | StopServer;; 71 | 72 | "info"|"-i") 73 | Info;; 74 | 75 | "help"|"-h") 76 | Help;; 77 | esac 78 | -------------------------------------------------------------------------------- /install: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | CURDIR=`pwd` 4 | APPNAME=`pwd | awk -F'/' '{print $(NF)}'` 5 | BAKGOPATH="$GOPATH" 6 | export GOPATH="$CURDIR:$GOPATH" 7 | 8 | echo 'GOPATH' `go env GOPATH` 9 | 10 | gofmt -w src 11 | 12 | DEBUG='' 13 | case $2 in 14 | "-D") 15 | DEBUG='-gcflags "-N -l" -ldflags "-s"' 16 | echo $DEBUG 17 | esac 18 | 19 | case $1 in 20 | ""|"-api") 21 | echo 'make apiserver' 22 | go clean apiserver 23 | go install apiserver 24 | echo 'make finished' 25 | ;; 26 | 27 | "-init") 28 | echo 'init start...' 29 | echo "go get -u github.com/futurez/litego/config" 30 | go get -u github.com/futurez/litego/config 31 | echo "go get -u github.com/futurez/litego/httplib" 32 | go get -u github.com/futurez/litego/httplib 33 | echo "go get -u github.com/futurez/litego/logger" 34 | go get -u github.com/futurez/litego/logger 35 | echo "go get -u github.com/futurez/litego/mysqlpool" 36 | go get -u github.com/futurez/litego/mysqlpool 37 | echo "go get -u github.com/futurez/litego/util" 38 | go get -u github.com/futurez/litego/util 39 | echo 'init finished' 40 | ;; 41 | 42 | esac 43 | 44 | export GOPATH="$BAKGOPATH" 45 | 46 | 47 | -------------------------------------------------------------------------------- /pic/freamwork.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QPlus/GotyeLive/54cfb1eaaff38e65c9a2e4875e83ca713e24c42b/pic/freamwork.jpg -------------------------------------------------------------------------------- /pic/gotyelive-group01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QPlus/GotyeLive/54cfb1eaaff38e65c9a2e4875e83ca713e24c42b/pic/gotyelive-group01.png -------------------------------------------------------------------------------- /pic/gotyelive1.0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QPlus/GotyeLive/54cfb1eaaff38e65c9a2e4875e83ca713e24c42b/pic/gotyelive1.0.png -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | #亲加直播(GotyeLive)——互动视频技术整体解决方案 2 | 3 | ##简介 4 | 随着移动互联网的发展以及移动设备的普及,网络宽带成本的下降更能让任何一个有手机的人都有向全世界做直播的能力。 5 | "人人都在直播"现象越发普遍,类似于映客、花椒这样的全民直播App也层出不穷。视频直播将继文字社交、图片社交、 6 | 语音社交后成为互联网社交新模式。 7 | 8 | 为更好帮助客户实现视频直播功能,快速拥有自己类似于花椒、映客的直播App,[亲加视频云](http://www.gotye.com.cn/live.html) 9 | (隶属于[亲加通讯云](http://www.gotye.com.cn/))在基于亲加直播SDK开发一款商业级的全民直播APP(亲加直播),并 10 | 且以开源的方式分享给直播创业者和业界人士,通过亲加全民直播开源项目的学习,就能更加快速、专业、稳定把视频直播技 11 | 术应用到不同行业的商业产品中,进军全民直播App的视频社交浪潮中。 12 | 13 | 14 | ##直播APP技术框架 15 |
16 | 直播APP技术框架图 17 |
18 | 19 | 目前亲加提供: 20 | 21 | [后台服务器(golang)](server.md)和[IOS App(object-C)](https://github.com/QPlus/GotyeLive_IOS) 22 | Android App亲加希望大家通过学习之后,有开源精神的程序员能够参与到这个开源项目当中,与亲加共同开发android版本。 23 | 24 | 25 | ##IOS APP 26 | [下载安装](http://fir.im/qjzb) 27 | 28 | 29 | 30 | ##亲加直播交流QQ群 31 | 全民直播App视频技术 : [202871487] 32 | 33 | 34 | -------------------------------------------------------------------------------- /server.md: -------------------------------------------------------------------------------- 1 | #亲加直播GotyeLive服务器程序 2 | 3 | ##简介 4 | 该项目是亲加直播客户端[QPlusLive For IOS](https://github.com/QPlus/GotyeLive_IOS)的直播业务服务器。 5 | 6 | 该项目是使用Golang编写的直播业务服务器,可以直接运行,为了方便大家测试使用,可以使用已编译版本,[点击下载] 7 | (https://github.com/QPlus/GotyeLive/blob/master/doc/gotyelive_server.tar.gz) 8 | 9 | 10 | 该项目完整安装全民直播APP而设计,目前是1.0版本,后期会不断更新,敬请期待。 11 | 12 | ## 使用方式 13 | 该项目需要使用Mysql,所以首先系统得安装Mysql。 14 | 15 | 创建数据库和表的SQL脚本为[gotye_open_live.sql](https://github.com/QPlus/GotyeLive/blob/master/doc/gotye_open_live.sql), 16 | 下载解压后的.tar.gz包里面既有。 17 | 18 | 压缩包中提供了编译好的支持`Linux`的可执行文件。 19 | 20 | 压缩包中的[config.ini](https://github.com/QPlus/GotyeLive/blob/master/doc/config.ini)是服务器的配置文件,其中的内容请安格式修改, 具体说明如下: 21 | ``` 22 | [apiserver] 23 | #服务器监听端口 24 | http_port = 8080 25 | 26 | [mysql] 27 | #数据库地址 28 | address = 192.168.1.10 29 | #数据库名 30 | dbname = gotye_open_live 31 | #数据库账号 32 | account = app 33 | #数据库密码 34 | password = 123456 35 | ``` 36 | 压缩包中的[run](https://github.com/QPlus/GotyeLive/blob/master/doc/run)是服务器启动脚本,使用说明如下: 37 | run -s or start : 启动服务器程序 38 | run -k or stop : 关闭服务器程序 39 | run -i or info : 查看服务器信息 40 | run -h or help : 获得脚本使用说明 41 | 42 | ##API说明 43 | 44 | [应用层协议]请查看[API_DOC](api_doc.md) 45 | 46 | 47 | -------------------------------------------------------------------------------- /src/apiserver/config.ini: -------------------------------------------------------------------------------- 1 | [apiserver] 2 | http_port = 11000 3 | 4 | [mysql] 5 | address = 192.168.1.141 6 | dbname = gotye_open_live 7 | account = fcloud 8 | password = fcloud2015 9 | -------------------------------------------------------------------------------- /src/apiserver/liveapi/authCode.go: -------------------------------------------------------------------------------- 1 | package liveapi 2 | 3 | import ( 4 | "apiserver/service" 5 | "encoding/json" 6 | "gotye_protocol" 7 | "io/ioutil" 8 | "net/http" 9 | 10 | "github.com/futurez/litego/httplib" 11 | "github.com/futurez/litego/logger" 12 | "github.com/futurez/litego/util" 13 | ) 14 | 15 | func AuthCode(w http.ResponseWriter, r *http.Request) { 16 | resp := gotye_protocol.AuthCodeResponse{} 17 | req := gotye_protocol.AuthCodeRequest{} 18 | 19 | readdata, err := ioutil.ReadAll(r.Body) 20 | if err != nil { 21 | logger.Warn("AuthCode : ", err.Error()) 22 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 23 | goto end 24 | } 25 | 26 | err = json.Unmarshal(readdata, &req) 27 | if err != nil { 28 | logger.Warn("AuthCode : reqdata not json ", string(readdata)) 29 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 30 | goto end 31 | } 32 | 33 | if !util.CheckPhone(req.Phone) { 34 | logger.Warn("AuthCode : phone is invalid. ", string(readdata)) 35 | resp.SetFormatStatus(gotye_protocol.API_PARAM_ERROR, "phone invalid.") 36 | goto end 37 | } 38 | 39 | logger.Info("AuthCode : phone=", req.Phone) 40 | service.RequestAuthCode(&resp, &req) 41 | 42 | end: 43 | resp.SetAccess("/live/AuthCode") 44 | httplib.HttpResponseJson(w, http.StatusOK, &resp) 45 | } 46 | -------------------------------------------------------------------------------- /src/apiserver/liveapi/createLiveRoom.go: -------------------------------------------------------------------------------- 1 | package liveapi 2 | 3 | import ( 4 | "apiserver/service" 5 | "encoding/json" 6 | "gotye_protocol" 7 | "io/ioutil" 8 | "net/http" 9 | 10 | "github.com/futurez/litego/httplib" 11 | "github.com/futurez/litego/logger" 12 | ) 13 | 14 | func CreateLiveRoom(w http.ResponseWriter, r *http.Request) { 15 | resp := gotye_protocol.CreateLiveRoomResponse{} 16 | req := gotye_protocol.CreateLiveRoomRequest{} 17 | 18 | readdata, err := ioutil.ReadAll(r.Body) 19 | if err != nil { 20 | logger.Warn("CreateLiveRoom : ", err.Error()) 21 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 22 | goto end 23 | } 24 | 25 | err = json.Unmarshal(readdata, &req) 26 | if err != nil { 27 | logger.Warn("CreateLiveRoom : reqdata not json ", string(readdata)) 28 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 29 | goto end 30 | } 31 | 32 | logger.Info("CreateLiveRoom : req = ", string(readdata)) 33 | service.CreateLiveRoom(&resp, &req) 34 | 35 | end: 36 | resp.SetAccess("/live/CreateLiveRoom") 37 | httplib.HttpResponseJson(w, http.StatusOK, &resp) 38 | } 39 | -------------------------------------------------------------------------------- /src/apiserver/liveapi/followLiveRoom.go: -------------------------------------------------------------------------------- 1 | package liveapi 2 | 3 | import ( 4 | "apiserver/service" 5 | "encoding/json" 6 | "gotye_protocol" 7 | "io/ioutil" 8 | "net/http" 9 | 10 | "github.com/futurez/litego/httplib" 11 | "github.com/futurez/litego/logger" 12 | ) 13 | 14 | func FollowLiveRoom(w http.ResponseWriter, r *http.Request) { 15 | resp := gotye_protocol.FollowLiveRoomResponse{} 16 | req := gotye_protocol.FollowLiveRoomRequest{} 17 | 18 | var status int 19 | 20 | readdata, err := ioutil.ReadAll(r.Body) 21 | if err != nil { 22 | logger.Warn("FollowLiveRoom : ", err.Error()) 23 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 24 | goto end 25 | } 26 | 27 | err = json.Unmarshal(readdata, &req) 28 | if err != nil { 29 | logger.Warn("FollowLiveRoom : reqdata not json ", string(readdata)) 30 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 31 | goto end 32 | } 33 | 34 | logger.Info("FollowLiveRoom : req=", string(readdata)) 35 | status = service.FollowLiveRoom(req.SessionId, req.LiveRoomId, req.IsFollow) 36 | if status != gotye_protocol.API_SUCCESS { 37 | logger.Warn("FollowLiveRoom : status=", status) 38 | } else { 39 | logger.Info("FollowLiveRoom : success ", string(readdata)) 40 | } 41 | resp.SetStatus(status) 42 | 43 | end: 44 | resp.SetAccess("/live/FollowLiveRoom") 45 | httplib.HttpResponseJson(w, http.StatusOK, &resp) 46 | } 47 | -------------------------------------------------------------------------------- /src/apiserver/liveapi/getLiveRoomList.go: -------------------------------------------------------------------------------- 1 | package liveapi 2 | 3 | import ( 4 | "apiserver/service" 5 | "encoding/json" 6 | "gotye_protocol" 7 | "io/ioutil" 8 | "net/http" 9 | 10 | "github.com/futurez/litego/httplib" 11 | "github.com/futurez/litego/logger" 12 | ) 13 | 14 | func GetLiveRoomList(w http.ResponseWriter, r *http.Request) { 15 | resp := gotye_protocol.ApiResponse{} 16 | req := gotye_protocol.GetLiveRoomListRequest{} 17 | 18 | readdata, err := ioutil.ReadAll(r.Body) 19 | if err != nil { 20 | logger.Warn("GetLiveRoomList : ", err.Error()) 21 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 22 | goto end 23 | } 24 | 25 | err = json.Unmarshal(readdata, &req) 26 | if err != nil { 27 | logger.Warn("GetLiveRoomList : reqdata not json ", string(readdata)) 28 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 29 | goto end 30 | } 31 | 32 | logger.Info("GetLiveRoomList : req=", string(readdata)) 33 | 34 | if req.Type == gotye_protocol.ALL_LIVE_ROOM_LIST { 35 | GetAllLiveRoomList(w, &req) 36 | return 37 | } else if req.Type == gotye_protocol.FOCUS_LIVE_ROOM_LIST { 38 | GetFcousLiveRoomList(w, &req) 39 | return 40 | } else { 41 | logger.Warn("GetLiveRoomList : unknown type=", req.Type) 42 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 43 | } 44 | 45 | end: 46 | resp.SetAccess("liveapi/GetLiveRoomList") 47 | logger.Info("GetLiveRoomList : resp=", resp) 48 | httplib.HttpResponseJson(w, http.StatusOK, &resp) 49 | } 50 | 51 | func GetAllLiveRoomList(w http.ResponseWriter, req *gotye_protocol.GetLiveRoomListRequest) { 52 | logger.Info("GetAllLiveRoomList : ") 53 | resp := gotye_protocol.GetAllLiveRoomListResponse{} 54 | resp.SetAccess("liveapi/GetLiveRoomList") 55 | 56 | service.GetAllLiveRoomList(&resp, req) 57 | 58 | logger.Info("GetAllLiveRoomList : resp=", resp) 59 | httplib.HttpResponseJson(w, http.StatusOK, &resp) 60 | } 61 | 62 | func GetFcousLiveRoomList(w http.ResponseWriter, req *gotye_protocol.GetLiveRoomListRequest) { 63 | logger.Info("GetFcousLiveRoomList : ") 64 | resp := gotye_protocol.GetFcousLiveRoomListResponse{} 65 | resp.SetAccess("liveapi/GetLiveRoomList") 66 | 67 | service.GetFcousLiveRoomList(&resp, req) 68 | httplib.HttpResponseJson(w, http.StatusOK, &resp) 69 | } 70 | -------------------------------------------------------------------------------- /src/apiserver/liveapi/getLiveroomNumber.go: -------------------------------------------------------------------------------- 1 | package liveapi 2 | 3 | import ( 4 | "apiserver/service" 5 | "encoding/json" 6 | "gotye_protocol" 7 | "io/ioutil" 8 | "net/http" 9 | 10 | "github.com/futurez/litego/httplib" 11 | "github.com/futurez/litego/logger" 12 | ) 13 | 14 | func GetLiveroomNumber(w http.ResponseWriter, r *http.Request) { 15 | var status int 16 | req := gotye_protocol.GetLiveroomNumberRequest{} 17 | resp := gotye_protocol.GetLiveroomNumberResponse{} 18 | 19 | readdata, err := ioutil.ReadAll(r.Body) 20 | if err != nil { 21 | logger.Warn("GetLiveroomNumber : ", err.Error()) 22 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 23 | goto end 24 | } 25 | 26 | err = json.Unmarshal(readdata, &req) 27 | if err != nil { 28 | logger.Warn("GetLiveroomNumber : not json = ", string(readdata)) 29 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 30 | goto end 31 | } 32 | 33 | logger.Info("GetLiveroomNumber : req=", string(readdata)) 34 | resp.Number, status = service.GetLiveroomNumber(req.SessionId, req.LiveroomId) 35 | resp.LiveroomId = req.LiveroomId 36 | resp.SetStatus(status) 37 | 38 | end: 39 | resp.SetAccess("/live/PushLiveStream") 40 | httplib.HttpResponseJson(w, http.StatusOK, &resp) 41 | } 42 | -------------------------------------------------------------------------------- /src/apiserver/liveapi/getMyLiveRoom.go: -------------------------------------------------------------------------------- 1 | package liveapi 2 | 3 | import ( 4 | "apiserver/service" 5 | "encoding/json" 6 | "gotye_protocol" 7 | "io/ioutil" 8 | "net/http" 9 | 10 | "github.com/futurez/litego/httplib" 11 | "github.com/futurez/litego/logger" 12 | ) 13 | 14 | func GetMyLiveRoom(w http.ResponseWriter, r *http.Request) { 15 | resp := gotye_protocol.GetMyLiveRoomResponse{} 16 | req := gotye_protocol.GetMyLiveRoomRequest{} 17 | 18 | readdata, err := ioutil.ReadAll(r.Body) 19 | if err != nil { 20 | logger.Warn("PushLiveStream : ", err.Error()) 21 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 22 | goto end 23 | } 24 | 25 | err = json.Unmarshal(readdata, &req) 26 | if err != nil { 27 | logger.Warn("PushLiveStream : reqdata not json ", string(readdata)) 28 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 29 | goto end 30 | } 31 | 32 | logger.Info("GetMyLiveRoom : req=", req) 33 | service.GetMyLiveRoom(&resp, &req) 34 | 35 | end: 36 | resp.SetAccess("/live/GetMyLiveRoom") 37 | httplib.HttpResponseJson(w, http.StatusOK, &resp) 38 | } 39 | -------------------------------------------------------------------------------- /src/apiserver/liveapi/getMyLiveRoomId.go: -------------------------------------------------------------------------------- 1 | package liveapi 2 | 3 | import ( 4 | "apiserver/service" 5 | "encoding/json" 6 | "gotye_protocol" 7 | "io/ioutil" 8 | "net/http" 9 | 10 | "github.com/futurez/litego/httplib" 11 | "github.com/futurez/litego/logger" 12 | ) 13 | 14 | func GetMyLiveRoomId(w http.ResponseWriter, r *http.Request) { 15 | resp := gotye_protocol.GetMyLiveRoomIdResponse{} 16 | req := gotye_protocol.GetMyLiveRoomIdRequest{} 17 | 18 | readdata, err := ioutil.ReadAll(r.Body) 19 | if err != nil { 20 | logger.Warn("PushLiveStream : ", err.Error()) 21 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 22 | goto end 23 | } 24 | 25 | err = json.Unmarshal(readdata, &req) 26 | if err != nil { 27 | logger.Warn("PushLiveStream : reqdata not json ", string(readdata)) 28 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 29 | goto end 30 | } 31 | 32 | logger.Info("GetMyLiveRoomId : req=", req) 33 | service.GetMyLiveRoomId(&resp, &req) 34 | 35 | end: 36 | resp.SetAccess("/live/GetMyLiveRoomId") 37 | httplib.HttpResponseJson(w, http.StatusOK, &resp) 38 | } 39 | -------------------------------------------------------------------------------- /src/apiserver/liveapi/getUserHeadPic.go: -------------------------------------------------------------------------------- 1 | package liveapi 2 | 3 | import ( 4 | "apiserver/service" 5 | "gotye_protocol" 6 | "net/http" 7 | "strconv" 8 | 9 | "github.com/futurez/litego/httplib" 10 | "github.com/futurez/litego/logger" 11 | ) 12 | 13 | // http://xxx:xx/live/GetUserHeadPic?id= 14 | func GetUserHeadPic(w http.ResponseWriter, r *http.Request) { 15 | resp := gotye_protocol.GetUserHeadPicResponse{} 16 | r.ParseMultipartForm(32 << 20) 17 | imageId, err := strconv.Atoi(r.FormValue("id")) 18 | if err != nil { 19 | logger.Warn("GetUserHeadPic : convert id err.") 20 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 21 | resp.SetAccess("/live/GetUserHeadPic") 22 | httplib.HttpResponseJson(w, http.StatusOK, resp) 23 | } 24 | 25 | if imageId == 0 { 26 | logger.Warn("GetUserHeadPic : id is 0.") 27 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 28 | resp.SetAccess("/live/GetUserHeadPic") 29 | httplib.HttpResponseJson(w, http.StatusOK, resp) 30 | return 31 | } 32 | 33 | headPic, err := service.GetHeadPicById(int64(imageId)) 34 | if err != nil { 35 | logger.Warn("GetUserHeadPic : failed.") 36 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 37 | resp.SetAccess("/live/GetUserHeadPic") 38 | httplib.HttpResponseJson(w, http.StatusOK, resp) 39 | } else { 40 | logger.Infof("GetUserHeadPic : headPicId=%d, headPic=%d", imageId, len(headPic)) 41 | httplib.HttpResponseImage(w, headPic) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/apiserver/liveapi/login.go: -------------------------------------------------------------------------------- 1 | package liveapi 2 | 3 | import ( 4 | "apiserver/service" 5 | "encoding/json" 6 | "gotye_protocol" 7 | "io/ioutil" 8 | "net/http" 9 | 10 | "github.com/futurez/litego/httplib" 11 | "github.com/futurez/litego/logger" 12 | ) 13 | 14 | func Login(w http.ResponseWriter, r *http.Request) { 15 | resp := gotye_protocol.LoginResponse{} 16 | req := gotye_protocol.LoginRequest{} 17 | 18 | readdata, err := ioutil.ReadAll(r.Body) 19 | if err != nil { 20 | logger.Warn("Login : ", err.Error()) 21 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 22 | goto end 23 | } 24 | 25 | err = json.Unmarshal(readdata, &req) 26 | if err != nil { 27 | logger.Warn("Login : reqdata not json ", string(readdata)) 28 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 29 | goto end 30 | } 31 | logger.Info("Login : req = ", string(readdata)) 32 | service.UserLogin(&resp, &req) 33 | end: 34 | resp.SetAccess("/live/Login") 35 | httplib.HttpResponseJson(w, http.StatusOK, &resp) 36 | } 37 | -------------------------------------------------------------------------------- /src/apiserver/liveapi/modifyMyLiveRoom.go: -------------------------------------------------------------------------------- 1 | // my_liveroom.go 2 | package liveapi 3 | 4 | import ( 5 | "apiserver/service" 6 | "encoding/json" 7 | "gotye_protocol" 8 | "io/ioutil" 9 | "net/http" 10 | 11 | "github.com/futurez/litego/httplib" 12 | "github.com/futurez/litego/logger" 13 | ) 14 | 15 | func ModifyMyLiveRoom(w http.ResponseWriter, r *http.Request) { 16 | resp := gotye_protocol.ModifyMyLiveRoomResponse{} 17 | req := gotye_protocol.ModifyMyLiveRoomRequest{} 18 | 19 | readdata, err := ioutil.ReadAll(r.Body) 20 | if err != nil { 21 | logger.Warn("ModifyMyLiveRoom : ", err.Error()) 22 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 23 | goto end 24 | } 25 | 26 | err = json.Unmarshal(readdata, &req) 27 | if err != nil { 28 | logger.Warn("ModifyMyLiveRoom : reqdata not json ", string(readdata)) 29 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 30 | goto end 31 | } 32 | 33 | logger.Info("ModifyMyLiveRoom : req=", string(readdata)) 34 | service.ModifyMyLiveRoom(&resp, &req) 35 | 36 | end: 37 | resp.SetAccess("/live/ModifyMyLiveRoom") 38 | httplib.HttpResponseJson(w, http.StatusOK, &resp) 39 | } 40 | -------------------------------------------------------------------------------- /src/apiserver/liveapi/modifyUserHeadPic.go: -------------------------------------------------------------------------------- 1 | package liveapi 2 | 3 | import ( 4 | "apiserver/service" 5 | "encoding/json" 6 | "gotye_protocol" 7 | "io/ioutil" 8 | "net/http" 9 | 10 | "github.com/futurez/litego/httplib" 11 | "github.com/futurez/litego/logger" 12 | ) 13 | 14 | func ModifyUserHeadPic(w http.ResponseWriter, r *http.Request) { 15 | resp := gotye_protocol.ModifyUserHeadPicResponse{} 16 | req := gotye_protocol.ModifyUserHeadPicRequest{} 17 | 18 | readdata, err := ioutil.ReadAll(r.Body) 19 | if err != nil { 20 | logger.Warn("ModifyUserHeadPic : ", err.Error()) 21 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 22 | goto end 23 | } 24 | 25 | err = json.Unmarshal(readdata, &req) 26 | if err != nil { 27 | logger.Warn("ModifyUserHeadPic : reqdata not json ", string(readdata)) 28 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 29 | goto end 30 | 31 | } 32 | 33 | if len(req.SessionID) == 0 { 34 | logger.Warn("ModifyUserHeadPic : sessionID is nul ") 35 | resp.SetStatus(gotye_protocol.API_EXPIRED_SESSION_ERROR) 36 | goto end 37 | } 38 | 39 | logger.Infof("ModifyUserHeadPic : req sessionId=%s, piclen=%d", req.SessionID, len(req.HeadPic)) 40 | service.UserHeadPicModify(&resp, &req) 41 | 42 | end: 43 | resp.SetAccess("/live/ModifyUserHeadPic") 44 | httplib.HttpResponseJson(w, http.StatusOK, &resp) 45 | } 46 | -------------------------------------------------------------------------------- /src/apiserver/liveapi/modifyUserInfo.go: -------------------------------------------------------------------------------- 1 | package liveapi 2 | 3 | import ( 4 | "apiserver/service" 5 | "encoding/json" 6 | "gotye_protocol" 7 | "io/ioutil" 8 | "net/http" 9 | 10 | "github.com/futurez/litego/httplib" 11 | "github.com/futurez/litego/logger" 12 | ) 13 | 14 | func ModifyUserInfo(w http.ResponseWriter, r *http.Request) { 15 | resp := gotye_protocol.ModifyUserInfoResponse{} 16 | req := gotye_protocol.ModifyUserInfoRequest{} 17 | 18 | readdata, err := ioutil.ReadAll(r.Body) 19 | if err != nil { 20 | logger.Warn("ModifyUserInfo : ", err.Error()) 21 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 22 | goto end 23 | } 24 | 25 | err = json.Unmarshal(readdata, &req) 26 | if err != nil { 27 | logger.Warn("ModifyUserInfo : reqdata not json ", string(readdata)) 28 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 29 | goto end 30 | } 31 | 32 | if len(req.SessionID) == 0 { 33 | logger.Warn("ModifyUserInfo : sessionID is nul ", string(readdata)) 34 | resp.SetStatus(gotye_protocol.API_EXPIRED_SESSION_ERROR) 35 | goto end 36 | } 37 | 38 | if len(req.NickName) == 0 && len(req.Address) == 0 && 39 | (req.Sex != 1 || req.Sex != 2) { 40 | logger.Warn("ModifyUserInfo : param error. ", string(readdata)) 41 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 42 | goto end 43 | } 44 | 45 | logger.Info("ModifyUserInfo : req=", string(readdata)) 46 | service.UserInfoModify(&resp, &req) 47 | 48 | end: 49 | resp.SetAccess("/live/ModifyUserInfo") 50 | httplib.HttpResponseJson(w, http.StatusOK, &resp) 51 | } 52 | -------------------------------------------------------------------------------- /src/apiserver/liveapi/modifyUserPwd.go: -------------------------------------------------------------------------------- 1 | package liveapi 2 | 3 | import ( 4 | "apiserver/service" 5 | "encoding/json" 6 | "gotye_protocol" 7 | "io/ioutil" 8 | "net/http" 9 | 10 | "github.com/futurez/litego/httplib" 11 | "github.com/futurez/litego/logger" 12 | ) 13 | 14 | func ModifyUserPwd(w http.ResponseWriter, r *http.Request) { 15 | resp := gotye_protocol.ModifyUserPwdResponse{} 16 | req := gotye_protocol.ModifyUserPwdRequest{} 17 | 18 | readdata, err := ioutil.ReadAll(r.Body) 19 | if err != nil { 20 | logger.Warn("ModifyUserPwd : ", err.Error()) 21 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 22 | goto end 23 | } 24 | 25 | err = json.Unmarshal(readdata, &req) 26 | if err != nil { 27 | logger.Warn("ModifyUserPwd : reqdata not json ", string(readdata)) 28 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 29 | goto end 30 | } 31 | 32 | logger.Info("ModifyUserPwd : req=", string(readdata)) 33 | service.UserPwdModify(&resp, &req) 34 | 35 | end: 36 | resp.SetAccess("/live/ModifyUserPwd") 37 | httplib.HttpResponseJson(w, http.StatusOK, &resp) 38 | } 39 | -------------------------------------------------------------------------------- /src/apiserver/liveapi/payApi.go: -------------------------------------------------------------------------------- 1 | package liveapi 2 | 3 | import ( 4 | "apiserver/service" 5 | "encoding/json" 6 | "gotye_protocol" 7 | "io/ioutil" 8 | "net/http" 9 | 10 | "github.com/futurez/litego/httplib" 11 | "github.com/futurez/litego/logger" 12 | ) 13 | 14 | func ChargeRMB(w http.ResponseWriter, r *http.Request) { 15 | req := gotye_protocol.ChargeRMBRequest{} 16 | resp := gotye_protocol.ChargeRMBResponse{} 17 | 18 | readdata, err := ioutil.ReadAll(r.Body) 19 | if err != nil { 20 | logger.Warn("ChargeRMB : ", err.Error()) 21 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 22 | goto end 23 | } 24 | 25 | err = json.Unmarshal(readdata, &req) 26 | if err != nil { 27 | logger.Warn("ChargeRMB : not json = ", string(readdata)) 28 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 29 | goto end 30 | } 31 | 32 | logger.Info("ChargeRMB : req=", string(readdata)) 33 | service.ChargeRMB(&resp, &req) 34 | 35 | end: 36 | resp.SetAccess("/pay/ChargeRMB") 37 | httplib.HttpResponseJson(w, http.StatusOK, &resp) 38 | } 39 | 40 | func PayQinCoin(w http.ResponseWriter, r *http.Request) { 41 | req := gotye_protocol.PayQinCoinRequest{} 42 | resp := gotye_protocol.PayQinCoinResponse{} 43 | 44 | readdata, err := ioutil.ReadAll(r.Body) 45 | if err != nil { 46 | logger.Warn("PayQinCoin : ", err.Error()) 47 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 48 | goto end 49 | } 50 | 51 | err = json.Unmarshal(readdata, &req) 52 | if err != nil { 53 | logger.Warn("PayQinCoin : not json = ", string(readdata)) 54 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 55 | goto end 56 | } 57 | 58 | logger.Info("PayQinCoin : req=", string(readdata)) 59 | service.PayQinCoin(&resp, &req) 60 | 61 | end: 62 | resp.SetAccess("/pay/PayQinCoin") 63 | httplib.HttpResponseJson(w, http.StatusOK, &resp) 64 | } 65 | 66 | func GetPayAccount(w http.ResponseWriter, r *http.Request) { 67 | req := gotye_protocol.GetPayAccountRequest{} 68 | resp := gotye_protocol.GetPayAccountResponse{} 69 | 70 | readdata, err := ioutil.ReadAll(r.Body) 71 | if err != nil { 72 | logger.Warn("GetPayAccount : ", err.Error()) 73 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 74 | goto end 75 | } 76 | 77 | err = json.Unmarshal(readdata, &req) 78 | if err != nil { 79 | logger.Warn("GetPayAccount : not json = ", string(readdata)) 80 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 81 | goto end 82 | } 83 | 84 | logger.Info("GetPayAccount : req=", string(readdata)) 85 | service.GetPayAccount(&resp, &req) 86 | 87 | end: 88 | resp.SetAccess("/pay/GetPayAccount") 89 | httplib.HttpResponseJson(w, http.StatusOK, &resp) 90 | } 91 | -------------------------------------------------------------------------------- /src/apiserver/liveapi/playLiveStream.go: -------------------------------------------------------------------------------- 1 | package liveapi 2 | 3 | import ( 4 | "apiserver/service" 5 | "encoding/json" 6 | "gotye_protocol" 7 | "io/ioutil" 8 | "net/http" 9 | 10 | "github.com/futurez/litego/httplib" 11 | "github.com/futurez/litego/logger" 12 | ) 13 | 14 | func PlayLiveStream(w http.ResponseWriter, r *http.Request) { 15 | var status int 16 | req := gotye_protocol.PlayLiveStreamRequest{} 17 | resp := gotye_protocol.PlayLiveStreamResponse{} 18 | 19 | readdata, err := ioutil.ReadAll(r.Body) 20 | if err != nil { 21 | logger.Warn("PlayLiveStream : ", err.Error()) 22 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 23 | goto end 24 | } 25 | 26 | err = json.Unmarshal(readdata, &req) 27 | if err != nil { 28 | logger.Warn("PlayLiveStream : not json = ", string(readdata)) 29 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 30 | goto end 31 | } 32 | 33 | logger.Info("PlayLiveStream : req=", string(readdata)) 34 | status = service.PlayLiveStream(req.SessionId, req.LiveroomId, req.Status) 35 | resp.SetStatus(status) 36 | 37 | end: 38 | resp.SetAccess("/live/PushLiveStream") 39 | httplib.HttpResponseJson(w, http.StatusOK, &resp) 40 | } 41 | -------------------------------------------------------------------------------- /src/apiserver/liveapi/pushLiveStream.go: -------------------------------------------------------------------------------- 1 | package liveapi 2 | 3 | import ( 4 | "apiserver/service" 5 | "encoding/json" 6 | "gotye_protocol" 7 | "io/ioutil" 8 | "net/http" 9 | 10 | "github.com/futurez/litego/httplib" 11 | "github.com/futurez/litego/logger" 12 | ) 13 | 14 | func PushLiveStream(w http.ResponseWriter, r *http.Request) { 15 | resp := gotye_protocol.PushLiveStreamResponse{} 16 | req := gotye_protocol.PushLiveStreamRequest{} 17 | 18 | var status int 19 | 20 | readdata, err := ioutil.ReadAll(r.Body) 21 | if err != nil { 22 | logger.Warn("PushLiveStream : ", err.Error()) 23 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 24 | goto end 25 | } 26 | 27 | err = json.Unmarshal(readdata, &req) 28 | if err != nil { 29 | logger.Warn("PushLiveStream : not json = ", string(readdata)) 30 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 31 | goto end 32 | } 33 | 34 | logger.Info("PushLiveStream : req=", string(readdata)) 35 | status = service.PushingLiveStream(req.SessionId, req.LiveRoomId, req.Status, req.Timeout) 36 | resp.SetStatus(status) 37 | 38 | end: 39 | resp.SetAccess("/live/PushLiveStream") 40 | httplib.HttpResponseJson(w, http.StatusOK, &resp) 41 | } 42 | -------------------------------------------------------------------------------- /src/apiserver/liveapi/refreshPlayUrls.go: -------------------------------------------------------------------------------- 1 | package liveapi 2 | 3 | import ( 4 | "apiserver/service" 5 | "encoding/json" 6 | "gotye_protocol" 7 | "io/ioutil" 8 | "net/http" 9 | 10 | "github.com/futurez/litego/httplib" 11 | "github.com/futurez/litego/logger" 12 | ) 13 | 14 | type Req_RefreshPlayUrls struct { 15 | Secret string `json:"secret"` 16 | } 17 | 18 | type Resp_RefreshPlayUrls struct { 19 | gotye_protocol.ApiResponse 20 | } 21 | 22 | func RefreshPlayUrls(w http.ResponseWriter, r *http.Request) { 23 | req := Req_RefreshPlayUrls{} 24 | resp := Resp_RefreshPlayUrls{} 25 | 26 | readdata, err := ioutil.ReadAll(r.Body) 27 | if err != nil { 28 | logger.Warn("RefreshPlayUrls : ", err.Error()) 29 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 30 | goto end 31 | } 32 | 33 | err = json.Unmarshal(readdata, &req) 34 | if err != nil { 35 | logger.Warn("RefreshPlayUrls : reqdata not json ", string(readdata)) 36 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 37 | goto end 38 | } 39 | 40 | if req.Secret != "gotyeopenlive" { 41 | logger.Warn("RefreshPlayUrls : secret error ", string(readdata)) 42 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 43 | goto end 44 | } 45 | 46 | resp.SetStatus(service.RefreshPlayUrls()) 47 | 48 | end: 49 | resp.SetAccess("/admin/RefreshPlayUrls") 50 | httplib.HttpResponseJson(w, http.StatusOK, &resp) 51 | } 52 | -------------------------------------------------------------------------------- /src/apiserver/liveapi/register.go: -------------------------------------------------------------------------------- 1 | package liveapi 2 | 3 | import ( 4 | "apiserver/service" 5 | "encoding/json" 6 | "gotye_protocol" 7 | "io/ioutil" 8 | "net/http" 9 | 10 | "github.com/futurez/litego/httplib" 11 | "github.com/futurez/litego/logger" 12 | "github.com/futurez/litego/util" 13 | ) 14 | 15 | func Register(w http.ResponseWriter, r *http.Request) { 16 | resp := gotye_protocol.RegisterResponse{} 17 | req := gotye_protocol.RegisterRequest{} 18 | 19 | readdata, err := ioutil.ReadAll(r.Body) 20 | if err != nil { 21 | logger.Warn("Register : ", err.Error()) 22 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 23 | goto end 24 | } 25 | 26 | err = json.Unmarshal(readdata, &req) 27 | if err != nil { 28 | logger.Warn("Register : reqdata not json ", string(readdata)) 29 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 30 | goto end 31 | } 32 | 33 | if !util.CheckPhone(req.Phone) { 34 | logger.Warn("Register : phone is null. ", string(readdata)) 35 | resp.SetFormatStatus(gotye_protocol.API_PARAM_ERROR, "手机号码不存在") 36 | goto end 37 | } 38 | 39 | if len(req.Passwd) < 6 { 40 | logger.Warn("Register : pwd length less 6, =", req.Passwd) 41 | resp.SetFormatStatus(gotye_protocol.API_PARAM_ERROR, "密码小于6位") 42 | goto end 43 | } 44 | 45 | logger.Info("Register : phone=", req.Phone) 46 | service.UserRegister(&resp, &req) 47 | 48 | end: 49 | resp.SetAccess("/live/Register") 50 | httplib.HttpResponseJson(w, http.StatusOK, &resp) 51 | } 52 | -------------------------------------------------------------------------------- /src/apiserver/liveapi/router.go: -------------------------------------------------------------------------------- 1 | package liveapi 2 | 3 | import ( 4 | "github.com/futurez/litego/httplib" 5 | ) 6 | 7 | func StartHttpServer(host string, port int) { 8 | cfg := httplib.Config{ 9 | Host: host, 10 | Port: port, 11 | } 12 | httpSvc := httplib.NewServer(cfg) 13 | 14 | //user info 15 | httpSvc.HandleFunc("/live/Login", Login) 16 | httpSvc.HandleFunc("/live/Register", Register) 17 | httpSvc.HandleFunc("/live/ModifyUserInfo", ModifyUserInfo) 18 | httpSvc.HandleFunc("/live/ModifyUserHeadPic", ModifyUserHeadPic) 19 | httpSvc.HandleFunc("/live/ModifyUserPwd", ModifyUserPwd) 20 | httpSvc.HandleFunc("/live/GetUserHeadPic", GetUserHeadPic) 21 | httpSvc.HandleFunc("/live/AuthCode", AuthCode) 22 | 23 | //my live room 24 | httpSvc.HandleFunc("/live/CreateLiveRoom", CreateLiveRoom) 25 | httpSvc.HandleFunc("/live/ModifyMyLiveRoom", ModifyMyLiveRoom) 26 | httpSvc.HandleFunc("/live/GetMyLiveRoomId", GetMyLiveRoomId) 27 | httpSvc.HandleFunc("/live/GetMyLiveRoom", GetMyLiveRoom) 28 | 29 | //follow live room 30 | httpSvc.HandleFunc("/live/FollowLiveRoom", FollowLiveRoom) 31 | 32 | //list live room 33 | httpSvc.HandleFunc("/live/GetLiveRoomList", GetLiveRoomList) 34 | 35 | //push live stream 36 | httpSvc.HandleFunc("/live/PushLiveStream", PushLiveStream) 37 | 38 | //play live stream 39 | httpSvc.HandleFunc("/live/PlayLiveStream", PlayLiveStream) 40 | 41 | //get live room player number. 42 | httpSvc.HandleFunc("/live/GetLiveroomNumber", GetLiveroomNumber) 43 | 44 | //search live room 45 | httpSvc.HandleFunc("/live/SearchLiveRoom", SearchLiveRoom) 46 | 47 | //refresh domain 48 | httpSvc.HandleFunc("/admin/RefreshPlayUrls", RefreshPlayUrls) 49 | 50 | //pay system 51 | //httpSvc.HandleFunc("/pay/ChargeRMB", ChargeRMB) 52 | httpSvc.HandleFunc("/pay/PayQinCoin", PayQinCoin) 53 | httpSvc.HandleFunc("/pay/GetPayAccount", GetPayAccount) 54 | 55 | httpSvc.ListenAndServe() 56 | } 57 | -------------------------------------------------------------------------------- /src/apiserver/liveapi/searchLiveRoom.go: -------------------------------------------------------------------------------- 1 | package liveapi 2 | 3 | import ( 4 | "apiserver/service" 5 | "encoding/json" 6 | "gotye_protocol" 7 | "io/ioutil" 8 | "net/http" 9 | 10 | "github.com/futurez/litego/httplib" 11 | "github.com/futurez/litego/logger" 12 | ) 13 | 14 | func SearchLiveRoom(w http.ResponseWriter, r *http.Request) { 15 | resp := gotye_protocol.SearchLiveStreamResponse{} 16 | req := gotye_protocol.SearchLiveStreamRequest{} 17 | 18 | readdata, err := ioutil.ReadAll(r.Body) 19 | if err != nil { 20 | logger.Warn("SearchLiveRoom : ", err.Error()) 21 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 22 | goto end 23 | } 24 | 25 | err = json.Unmarshal(readdata, &req) 26 | if err != nil { 27 | logger.Warn("SearchLiveRoom : not json = ", string(readdata)) 28 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 29 | goto end 30 | } 31 | 32 | logger.Info("SearchLiveRoom : req=", string(readdata)) 33 | service.LiveRoomSearch(&resp, req.SessionId, req.Keyword) 34 | 35 | end: 36 | resp.SetAccess("/live/SearchLiveRoom") 37 | httplib.HttpResponseJson(w, http.StatusOK, &resp) 38 | } 39 | -------------------------------------------------------------------------------- /src/apiserver/main.go: -------------------------------------------------------------------------------- 1 | // main 2 | package main 3 | 4 | import ( 5 | "apiserver/liveapi" 6 | "apiserver/service" 7 | "os" 8 | 9 | "github.com/futurez/litego/config" 10 | "github.com/futurez/litego/logger" 11 | ) 12 | 13 | func main() { 14 | logger.Info("start apiserver!!!") 15 | 16 | iniconf, err := config.NewConfig(config.IniProtocol, "config.ini") 17 | if err != nil { 18 | logger.Error("main : ", err) 19 | os.Exit(1) 20 | } 21 | 22 | //init mysql 23 | mysql_addr := iniconf.GetString("mysql.address") 24 | mysql_dbname := iniconf.GetString("mysql.dbname") 25 | mysql_account := iniconf.GetString("mysql.account") 26 | mysql_passwd := iniconf.GetString("mysql.password") 27 | service.InitMysqlDbPool(mysql_addr, mysql_dbname, mysql_account, mysql_passwd) 28 | 29 | service.ReloadOnlineLiverooms() 30 | 31 | //start http server. 32 | //server_ip := iniconf.GetString("apiserver.server_ip", "*") 33 | http_port, _ := iniconf.GetInt("apiserver.http_port", 80) 34 | liveapi.StartHttpServer("", http_port) 35 | 36 | logger.StartAsyncSave() 37 | 38 | waiting := make(chan bool) 39 | logger.Info("exit ", <-waiting) 40 | } 41 | -------------------------------------------------------------------------------- /src/apiserver/service/authCode.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "fmt" 5 | "gotye_protocol" 6 | "net/url" 7 | "sync" 8 | 9 | "github.com/futurez/litego/httplib" 10 | "github.com/futurez/litego/logger" 11 | "github.com/futurez/litego/util" 12 | ) 13 | 14 | func SendAuthCode(phone string) (string, error) { 15 | v := url.Values{} 16 | v.Set("uid", SP_appInfo.smsUid) 17 | v.Set("auth", SP_appInfo.smsAuth) 18 | v.Set("mobile", phone) 19 | v.Set("expid", "0") 20 | v.Set("encode", "utf-8") 21 | 22 | authCode := util.AuthCode() 23 | 24 | v.Set("msg", fmt.Sprintf("验证码%s,请您进行校验,请勿泄漏.", authCode)) 25 | req := v.Encode() 26 | 27 | resp, err := httplib.HttpRequest("http://sms.10690221.com:9011/hy/", httplib.METHOD_GET, nil, []byte(req)) 28 | if err != nil { 29 | logger.Error("SendAuthCode : ", err.Error()) 30 | return "", err 31 | } 32 | logger.Infof("SendAuthCode : authCode=%s, resp=%s", authCode, string(resp)) 33 | return authCode, nil 34 | } 35 | 36 | type PhoneAuthcode struct { 37 | sync.RWMutex 38 | phoneMap map[string]string 39 | } 40 | 41 | func (p *PhoneAuthcode) Set(phone, code string) { 42 | p.Lock() 43 | defer p.Unlock() 44 | 45 | p.phoneMap[phone] = code 46 | } 47 | 48 | func (p *PhoneAuthcode) Delete(phone string) { 49 | p.RLock() 50 | defer p.RUnlock() 51 | 52 | delete(p.phoneMap, phone) 53 | } 54 | 55 | func (p *PhoneAuthcode) Check(phone, code string) bool { 56 | p.RLock() 57 | defer p.RUnlock() 58 | 59 | v, ok := p.phoneMap[phone] 60 | if !ok { 61 | return false 62 | } 63 | return (v == code) 64 | } 65 | 66 | var SP_phoneCode = &PhoneAuthcode{phoneMap: make(map[string]string, 0)} 67 | 68 | func RequestAuthCode(resp *gotye_protocol.AuthCodeResponse, req *gotye_protocol.AuthCodeRequest) { 69 | if DBIsPhoneExists(req.Phone) { 70 | resp.SetStatus(gotye_protocol.API_PHONE_EXISTS_ERROR) 71 | logger.Info("RequestAuthCode : phone = ", req.Phone, " is exists.") 72 | return 73 | } 74 | 75 | code, err := SendAuthCode(req.Phone) 76 | if err != nil { 77 | resp.SetStatus(gotye_protocol.API_SERVER_ERROR) 78 | logger.Info("RequestAuthCode : SendAuthCode failed.") 79 | return 80 | } 81 | 82 | SP_phoneCode.Set(req.Phone, code) 83 | logger.Infof("RequestAuthCode: phone=%s, code=%s", req.Phone, code) 84 | resp.SetStatus(gotye_protocol.API_SUCCESS) 85 | } 86 | -------------------------------------------------------------------------------- /src/apiserver/service/dbInit.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/futurez/litego/logger" 7 | "github.com/futurez/litego/mysqlpool" 8 | "github.com/futurez/litego/util" 9 | ) 10 | 11 | type AppInfo struct { 12 | username string 13 | password string 14 | accessSecret string 15 | appKey string 16 | smsUid string 17 | smsAuth string 18 | } 19 | 20 | var SP_appInfo = AppInfo{} 21 | 22 | var SP_MysqlDbPool *mysqlpool.MysqlConnPool 23 | 24 | func InitMysqlDbPool(host, dbname, account, password string) { 25 | var err error 26 | SP_MysqlDbPool, err = mysqlpool.NewMysqlConnPool(account, password, host, "3306", dbname, "utf8", 50) 27 | if err != nil { 28 | logger.Error("InitMysqlDbPool : ", err.Error()) 29 | os.Exit(1) 30 | } 31 | 32 | DBGetAppInfo() 33 | } 34 | 35 | func DBGetAppInfo() { 36 | db := SP_MysqlDbPool.GetDBConn() 37 | rows, err := db.Query("SELECT `key`, `value` FROM tbl_app") 38 | if err != nil { 39 | logger.Error("DBGetAppInfo : ", err.Error()) 40 | os.Exit(1) 41 | } 42 | 43 | var smsCode, smsPwd string 44 | 45 | for rows.Next() { 46 | var key, value string 47 | if err = rows.Scan(&key, &value); err != nil { 48 | logger.Error("DBGetAppInfo : ", err.Error()) 49 | os.Exit(1) 50 | } 51 | switch { 52 | case key == "username": 53 | SP_appInfo.username = value 54 | 55 | case key == "password": 56 | SP_appInfo.password = value 57 | 58 | case key == "accessSecret": 59 | SP_appInfo.accessSecret = value 60 | 61 | case key == "appkey": 62 | SP_appInfo.appKey = value 63 | 64 | case key == "smsUid": 65 | SP_appInfo.smsUid = value 66 | 67 | case key == "smsCode": 68 | smsCode = value 69 | 70 | case key == "smsPwd": 71 | smsPwd = value 72 | } 73 | } 74 | 75 | if len(SP_appInfo.username) == 0 || 76 | len(SP_appInfo.password) == 0 || 77 | len(SP_appInfo.accessSecret) == 0 || 78 | len(SP_appInfo.appKey) == 0 { 79 | logger.Error("appinfo : ", SP_appInfo) 80 | os.Exit(1) 81 | } 82 | 83 | SP_appInfo.smsAuth = util.Md5Hash(smsCode + smsPwd) 84 | logger.Info("appinfo : ", SP_appInfo) 85 | } 86 | -------------------------------------------------------------------------------- /src/apiserver/service/dbLiveRoom.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "database/sql" 5 | "fmt" 6 | "gotye_protocol" 7 | "strings" 8 | 9 | "github.com/futurez/litego/logger" 10 | ) 11 | 12 | func DBCreateLiveroom(userId, liveroomId int64, name, desc, topic, anchorPwd, assistPwd, userPwd, 13 | playRtmpUrls, playHlsUrls, playFlvUrls string) error { 14 | 15 | db := SP_MysqlDbPool.GetDBConn() 16 | res, err := db.Exec(`INSERT INTO tbl_liverooms(user_id,liveroom_id,liveroom_name,liveroom_desc,liveroom_topic,anchor_pwd, 17 | assist_pwd,user_pwd,play_rtmp_urls,play_hls_urls,play_flv_urls) VALUES(?,?,?,?,?,?,?,?,?,?,?)`, 18 | userId, liveroomId, name, desc, topic, anchorPwd, assistPwd, userPwd, playRtmpUrls, playHlsUrls, playFlvUrls) 19 | if err != nil { 20 | logger.Error("DBCreateLiveroom : ", err.Error()) 21 | return err 22 | } 23 | num, _ := res.RowsAffected() 24 | logger.Info("DBCreateLiveroom : RowsAffected=", num) 25 | return nil 26 | } 27 | 28 | func DBGetLiveRoomByUserId(user_id int64) (liveroomInfo gotye_protocol.LiveRoomInfo, ok bool) { 29 | 30 | db := SP_MysqlDbPool.GetDBConn() 31 | err := db.QueryRow(`SELECT liveroom_id, liveroom_name, liveroom_desc, liveroom_topic, anchor_pwd, user_pwd, 32 | play_rtmp_urls, play_hls_urls, play_flv_urls FROM tbl_liverooms WHERE user_id=?`, 33 | user_id).Scan(&liveroomInfo.LiveRoomId, &liveroomInfo.LiveRoomName, &liveroomInfo.LiveRoomDesc, 34 | &liveroomInfo.LiveRoomTopic, &liveroomInfo.LiveAnchorPwd, &liveroomInfo.LiveUserPwd, 35 | &liveroomInfo.PlayRtmpUrl, &liveroomInfo.PlayHlsUrl, &liveroomInfo.PlayFlvUrl) 36 | 37 | switch { 38 | case err == sql.ErrNoRows: 39 | logger.Warnf("DBGetLiveRoomByUserId : user_id=%d not have liveroom_id.", user_id) 40 | ok = false 41 | case err != nil: 42 | logger.Error("DBGetLiveRoomByUserId : ", err.Error()) 43 | ok = false 44 | default: 45 | logger.Info("DBGetLiveRoomByUserId : liveroomInfo", liveroomInfo) 46 | ok = true 47 | } 48 | return 49 | } 50 | 51 | func DBGetLiveroomIdByUserId(user_id int64) (liveroom_id int64) { 52 | db := SP_MysqlDbPool.GetDBConn() 53 | err := db.QueryRow("select liveroom_id from tbl_liverooms where user_id=?", user_id).Scan(&liveroom_id) 54 | switch { 55 | case err == sql.ErrNoRows: 56 | logger.Infof("GetLiveroomIdByUserId : user_id=%d not have liveroom_id.", user_id) 57 | case err != nil: 58 | logger.Error("GetLiveroomIdByUserId : ", err.Error()) 59 | default: 60 | logger.Infof("GetLiveroomIdByUserId : user_id=%d have liveroom_id = %d.", user_id, liveroom_id) 61 | } 62 | return 63 | } 64 | 65 | func DBModifyLiveRoomInfo(roomId int64, roomName, anchorPwd, assistPwd, userPwd, anchorDesc, contentDesc string) error { 66 | db := SP_MysqlDbPool.GetDBConn() 67 | 68 | var setValue []string 69 | if len(roomName) > 0 { 70 | setValue = append(setValue, fmt.Sprintf("liveroom_name='%s'", roomName)) 71 | } 72 | if len(anchorPwd) > 0 { 73 | setValue = append(setValue, fmt.Sprintf("anchor_pwd='%s'", anchorPwd)) 74 | } 75 | if len(assistPwd) > 0 { 76 | setValue = append(setValue, fmt.Sprintf("assist_pwd='%s'", assistPwd)) 77 | } 78 | if len(userPwd) > 0 { 79 | setValue = append(setValue, fmt.Sprintf("user_pwd='%s'", userPwd)) 80 | } 81 | if len(anchorDesc) > 0 { 82 | setValue = append(setValue, fmt.Sprintf("liveroom_desc='%s'", anchorDesc)) 83 | } 84 | if len(contentDesc) > 0 { 85 | setValue = append(setValue, fmt.Sprintf("liveroom_topic='%s'", contentDesc)) 86 | } 87 | setData := strings.Join(setValue, ",") 88 | sql := fmt.Sprintf("UPDATE tbl_liverooms SET %s WHERE liveroom_id=%d", setData, roomId) 89 | 90 | logger.Info("DBModifyLiveRoomInfo SQL=", sql) 91 | result, err := db.Exec(sql) 92 | if err != nil { 93 | logger.Error("DBModifyLiveRoomInfo : ", err.Error()) 94 | return err 95 | } 96 | num, _ := result.RowsAffected() 97 | logger.Info("DBModifyLiveRoomInfo : RowsAffected=", num) 98 | return nil 99 | } 100 | 101 | func DBAddFollowLiveRoom(userId int64, liveRoomId int64) error { 102 | db := SP_MysqlDbPool.GetDBConn() 103 | result, err := db.Exec("INSERT INTO tbl_follow_liverooms(user_id,liveroom_id) VALUES(?,?)", userId, liveRoomId) 104 | if err != nil { 105 | logger.Error("DBAddFollowLiveRoom : ", err.Error()) 106 | return err 107 | } 108 | num, _ := result.LastInsertId() 109 | logger.Info("DBAddFollowLiveRoom : LastInsertId=", num) 110 | return nil 111 | } 112 | 113 | func DBDelFollowLiveRoom(userId int64, liveRoomId int64) error { 114 | db := SP_MysqlDbPool.GetDBConn() 115 | result, err := db.Exec("DELETE FROM tbl_follow_liverooms WHERE user_id=? AND liveroom_id=?", userId, liveRoomId) 116 | if err != nil { 117 | logger.Error("DBDelFollowLiveRoom : ", err.Error()) 118 | return err 119 | } 120 | num, _ := result.RowsAffected() 121 | logger.Info("DBDelFollowLiveRoom : RowsAffected=", num) 122 | return nil 123 | } 124 | 125 | func DBGetFollowCount(liveRoomId int64) (count int) { 126 | db := SP_MysqlDbPool.GetDBConn() 127 | err := db.QueryRow("SELECT COUNT(*) as count FROM tbl_follow_liverooms where liveroom_id=?", liveRoomId).Scan(&count) 128 | switch { 129 | case err == sql.ErrNoRows: 130 | logger.Errorf("DBGetFollowCount : get liveroom_id=%d follow error.", liveRoomId) 131 | case err != nil: 132 | logger.Error("DBGetFollowCount : ", err.Error()) 133 | default: 134 | logger.Infof("DBGetFollowCount : liveroom_id=%d,count=%d", liveRoomId, count) 135 | } 136 | return 137 | } 138 | 139 | func DBReloadOnlineLiveroom() *[]onlineLiveroom { 140 | db := SP_MysqlDbPool.GetDBConn() 141 | rows, err := db.Query("SELECT liveroom_id, player_num, need_up FROM tbl_online_liverooms") 142 | if err != nil { 143 | logger.Error("DBReloadOnlineLiveroom : query err=", err.Error()) 144 | return nil 145 | } 146 | defer rows.Close() 147 | 148 | var ( 149 | rooms []onlineLiveroom 150 | room onlineLiveroom 151 | ) 152 | 153 | for rows.Next() { 154 | err = rows.Scan(&room.liveroomId, &room.playerNum, &room.needup) 155 | if err != nil { 156 | logger.Error("DBReloadOnlineLiveroom : scan err=", err.Error()) 157 | return nil 158 | } 159 | logger.Debug("DBReloadOnlineLiveroom : liveroomId=", room.liveroomId, ",playnum=", room.playerNum) 160 | rooms = append(rooms, room) 161 | } 162 | return &rooms 163 | } 164 | 165 | func DBAddOnlineLiveRoom(liveRoomId int64) error { 166 | db := SP_MysqlDbPool.GetDBConn() 167 | result, err := db.Exec("INSERT INTO tbl_online_liverooms(liveroom_id) VALUES(?)", liveRoomId) 168 | if err != nil { 169 | logger.Error("DBAddOnlineLiveRoom : ", err.Error()) 170 | return err 171 | } 172 | num, _ := result.LastInsertId() 173 | logger.Info("DBAddOnlineLiveRoom : LastInsertId=", num) 174 | return nil 175 | } 176 | 177 | func DBDelOnlineLiveRoom(liveRoomId int64) error { 178 | db := SP_MysqlDbPool.GetDBConn() 179 | result, err := db.Exec("DELETE FROM tbl_online_liverooms WHERE liveroom_id=?", liveRoomId) 180 | if err != nil { 181 | logger.Error("DBDelOnlineLiveRoom : ", err.Error()) 182 | return err 183 | } 184 | num, _ := result.RowsAffected() 185 | logger.Info("DBDelOnlineLiveRoom : RowsAffected=", num) 186 | return nil 187 | } 188 | 189 | func DBIsOnlineLiveRoom(liveRoomId int64) int8 { 190 | db := SP_MysqlDbPool.GetDBConn() 191 | var count int8 192 | err := db.QueryRow("SELECT COUNT(*) AS count FROM tbl_online_liverooms WHERE liveroom_id=?", liveRoomId).Scan(&count) 193 | switch { 194 | case err == sql.ErrNoRows: 195 | logger.Errorf("DBIsOnlineLiveRoom : get liveroom_id=%d follow error.", liveRoomId) 196 | case err != nil: 197 | logger.Error("DBIsOnlineLiveRoom : ", err.Error()) 198 | default: 199 | logger.Infof("DBIsOnlineLiveRoom : liveroom_id=%d,count=%d", liveRoomId, count) 200 | } 201 | return count 202 | } 203 | 204 | func DBUpdateOnlineLiveRoom(liveroomId int64, num int) error { 205 | db := SP_MysqlDbPool.GetDBConn() 206 | result, err := db.Exec("UPDATE tbl_online_liverooms SET player_num=? WHERE liveroom_id=?", num, liveroomId) 207 | if err != nil { 208 | logger.Warn("DBUpdateOnlineLiveRoom : ", err.Error()) 209 | return err 210 | } 211 | line, _ := result.RowsAffected() 212 | logger.Infof("DBUpdateOnlineLiveRoom : liveroomid=%d, num=%d, RowsAffected=%d", liveroomId, num, line) 213 | return nil 214 | } 215 | 216 | func DBIsFollowLiveRoom(userId, liveroomId int64) int8 { 217 | db := SP_MysqlDbPool.GetDBConn() 218 | var count int8 219 | err := db.QueryRow("SELECT COUNT(*) as count FROM tbl_follow_liverooms WHERE user_id=? AND liveroom_id=?", userId, liveroomId).Scan(&count) 220 | switch { 221 | case err == sql.ErrNoRows: 222 | logger.Errorf("DBGetFollowCount : get liveroom_id=%d follow error.", liveroomId) 223 | case err != nil: 224 | logger.Error("DBGetFollowCount : ", err.Error()) 225 | default: 226 | logger.Infof("DBGetFollowCount : userId=%d, liveroom_id=%d,count=%d", userId, liveroomId, count) 227 | } 228 | return count 229 | } 230 | 231 | func DBGetLiveRoomByLiveroomId(resp *gotye_protocol.SearchLiveStreamResponse, liveroomId int64) error { 232 | db := SP_MysqlDbPool.GetDBConn() 233 | err := db.QueryRow(`SELECT a.liveroom_name, a.liveroom_desc, a.liveroom_topic, a.anchor_pwd, a.user_pwd, 234 | a.play_rtmp_urls, a.play_hls_urls, a.play_flv_urls, b.nickname, b.headpic_id FROM tbl_liverooms a INNER 235 | JOIN tbl_users b ON a.user_id=b.user_id WHERE a.liveroom_id=?`, liveroomId).Scan(&resp.LiveRoomName, 236 | &resp.LiveRoomDesc, &resp.LiveRoomTopic, &resp.LiveAnchorPwd, &resp.LiveUserPwd, &resp.PlayRtmpUrl, 237 | &resp.PlayHlsUrl, &resp.PlayFlvUrl, &resp.AnchorName, &resp.HeadPicId) 238 | 239 | switch { 240 | case err == sql.ErrNoRows: 241 | logger.Warn("DBGetLiveRoomByLiveroomId : not have liveroom_id=", liveroomId) 242 | return err 243 | case err != nil: 244 | logger.Error("DBGetLiveRoomByLiveroomId : ", err.Error()) 245 | return err 246 | default: 247 | logger.Info("DBGetLiveRoomByLiveroomId : search success liveroomId=", liveroomId) 248 | resp.LiveRoomId = liveroomId 249 | return nil 250 | } 251 | } 252 | 253 | func DBGetAllLiveRoomList(resp *gotye_protocol.GetAllLiveRoomListResponse, lastIndex int64, count int) (int64, error) { 254 | db := SP_MysqlDbPool.GetDBConn() 255 | 256 | var ( 257 | rows *sql.Rows 258 | err error 259 | ) 260 | 261 | if lastIndex == 0 { 262 | rows, err = db.Query(`SELECT b.id, a.liveroom_id, a.liveroom_name, a.liveroom_desc, a.liveroom_topic, 263 | a.anchor_pwd, a.user_pwd, a.play_rtmp_urls, a.play_hls_urls, a.play_flv_urls, c.nickname, c.headpic_id 264 | FROM tbl_liverooms a INNER JOIN tbl_online_liverooms b INNER JOIN tbl_users c 265 | ON a.liveroom_id=b.liveroom_id AND a.user_id=c.user_id 266 | ORDER BY b.pushing_time DESC LIMIT ?`, count) 267 | } else { 268 | rows, err = db.Query(`SELECT b.id, a.liveroom_id, a.liveroom_name, a.liveroom_desc, a.liveroom_topic, 269 | a.anchor_pwd, a.user_pwd, a.play_rtmp_urls, a.play_hls_urls, a.play_flv_urls, c.nickname, c.headpic_id 270 | FROM tbl_liverooms a INNER JOIN tbl_online_liverooms b INNER JOIN tbl_users c 271 | ON a.liveroom_id=b.liveroom_id AND a.user_id=c.user_id 272 | ORDER BY b.pushing_time DESC LIMIT ?,?`, lastIndex, count) 273 | } 274 | defer rows.Close() 275 | 276 | if err != nil { 277 | logger.Error("DBGetAllLiveRoomList : ", err.Error()) 278 | return lastIndex, err 279 | } 280 | lastId := lastIndex 281 | for rows.Next() { 282 | var info gotye_protocol.LiveRoomInfo 283 | if err = rows.Scan(&lastId, &info.LiveRoomId, &info.LiveRoomName, &info.LiveRoomDesc, 284 | &info.LiveRoomTopic, &info.LiveAnchorPwd, &info.LiveUserPwd, &info.PlayRtmpUrl, &info.PlayHlsUrl, 285 | &info.PlayFlvUrl, &info.AnchorName, &info.HeadPicId); err != nil { 286 | logger.Error("DBGetAllLiveRoomList : ", err.Error()) 287 | resp.List = resp.List[:0] 288 | return lastIndex, err 289 | } 290 | info.FollowCount = DBGetFollowCount(info.LiveRoomId) 291 | logger.Info("DBGetAllLiveRoomList: info=", info) 292 | resp.List = append(resp.List, info) 293 | } 294 | if err = rows.Err(); err != nil { 295 | logger.Error("DBGetAllLiveRoomList : ", err.Error()) 296 | resp.List = resp.List[:0] 297 | return lastIndex, err 298 | } 299 | return lastId, nil 300 | } 301 | 302 | func DBGetOnlineFocusLiveRoomList( 303 | resp *gotye_protocol.GetFcousLiveRoomListResponse, userId, lastIndex int64, count int) (int64, error) { 304 | 305 | db := SP_MysqlDbPool.GetDBConn() 306 | var ( 307 | rows *sql.Rows 308 | err error 309 | ) 310 | 311 | if lastIndex == 0 { 312 | rows, err = db.Query(`SELECT b.id, a.liveroom_id, a.liveroom_name, a.liveroom_desc, a.liveroom_topic, 313 | a.anchor_pwd, a.user_pwd, a.play_rtmp_urls, a.play_hls_urls, a.play_flv_urls, c.nickname, c.headpic_id 314 | FROM tbl_liverooms a INNER JOIN tbl_online_liverooms b INNER JOIN tbl_users c 315 | ON a.liveroom_id=b.liveroom_id AND a.user_id=c.user_id 316 | WHERE a.liveroom_id IN (SELECT liveroom_id FROM tbl_follow_liverooms WHERE user_id=?) 317 | ORDER BY b.pushing_time DESC LIMIT ?`, userId, count) 318 | } else { 319 | rows, err = db.Query(`SELECT b.id, a.liveroom_id, a.liveroom_name, a.liveroom_desc, a.liveroom_topic, 320 | a.anchor_pwd, a.user_pwd, a.play_rtmp_urls, a.play_hls_urls, a.play_flv_urls, c.nickname, c.headpic_id 321 | FROM tbl_liverooms a INNER JOIN tbl_online_liverooms b INNER JOIN tbl_users c 322 | ON a.liveroom_id=b.liveroom_id AND a.user_id=c.user_id 323 | WHERE a.liveroom_id IN (SELECT liveroom_id FROM tbl_follow_liverooms WHERE user_id=?) 324 | ORDER BY b.pushing_time DESC LIMIT ?,?`, userId, lastIndex, count) 325 | } 326 | 327 | if err != nil { 328 | logger.Error("DBGetAllLiveRoomList : ", err.Error()) 329 | return lastIndex, err 330 | } 331 | 332 | lastId := lastIndex 333 | for rows.Next() { 334 | var info gotye_protocol.LiveRoomInfo 335 | if err = rows.Scan(&lastId, &info.LiveRoomId, &info.LiveRoomName, &info.LiveRoomDesc, 336 | &info.LiveRoomTopic, &info.LiveAnchorPwd, &info.LiveUserPwd, &info.PlayRtmpUrl, &info.PlayHlsUrl, 337 | &info.PlayFlvUrl, &info.AnchorName, &info.HeadPicId); err != nil { 338 | logger.Error("DBGetAllLiveRoomList : ", err.Error()) 339 | resp.OnlineList = resp.OnlineList[:0] 340 | return lastIndex, err 341 | } 342 | info.FollowCount = DBGetFollowCount(info.LiveRoomId) 343 | info.IsFollow = 1 344 | logger.Info("DBGetAllLiveRoomList: info=", info) 345 | resp.OnlineList = append(resp.OnlineList, info) 346 | } 347 | if err = rows.Err(); err != nil { 348 | logger.Error("DBGetAllLiveRoomList : ", err.Error()) 349 | resp.OnlineList = resp.OnlineList[:0] 350 | return lastIndex, err 351 | } 352 | return lastId, nil 353 | } 354 | 355 | func DBGetOfflineFocusLiveRoomList( 356 | resp *gotye_protocol.GetFcousLiveRoomListResponse, userId, lastIndex int64, count int) (int64, error) { 357 | 358 | db := SP_MysqlDbPool.GetDBConn() 359 | var ( 360 | rows *sql.Rows 361 | err error 362 | ) 363 | 364 | if lastIndex == 0 { 365 | rows, err = db.Query(`SELECT a.user_id, a.nickname, a.headpic_id, b.liveroom_id, b.liveroom_name, b.liveroom_desc, 366 | b.liveroom_topic, b.anchor_pwd, b.user_pwd, b.play_rtmp_urls, b.play_hls_urls, b.play_flv_urls 367 | FROM tbl_users a INNER JOIN tbl_liverooms b ON a.user_id=b.user_id 368 | WHERE b.liveroom_id IN (SELECT liveroom_id FROM tbl_follow_liverooms 369 | WHERE user_id=? AND (liveroom_id NOT IN (SELECT liveroom_id FROM tbl_online_liverooms))) 370 | ORDER BY a.user_id DESC LIMIT ?`, userId, count) 371 | } else { 372 | rows, err = db.Query(`SELECT a.user_id, a.nickname, a.headpic_id, b.liveroom_id, b.liveroom_name, b.liveroom_desc, 373 | b.liveroom_topic, b.anchor_pwd, b.user_pwd, b.play_rtmp_urls, b.play_hls_urls, b.play_flv_urls 374 | FROM tbl_users a INNER JOIN tbl_liverooms b ON a.user_id=b.user_id 375 | WHERE b.liveroom_id IN (SELECT liveroom_id FROM tbl_follow_liverooms 376 | WHERE user_id=? AND (liveroom_id NOT IN (SELECT liveroom_id FROM tbl_online_liverooms))) 377 | ORDER BY a.user_id DESC LIMIT ?,?`, userId, lastIndex, count) 378 | } 379 | 380 | if err != nil { 381 | logger.Error("DBGetAllLiveRoomList : ", err.Error()) 382 | return lastIndex, err 383 | } 384 | 385 | lastuserId := lastIndex 386 | for rows.Next() { 387 | var info gotye_protocol.LiveRoomInfo 388 | if err = rows.Scan(&lastuserId, &info.AnchorName, &info.HeadPicId, &info.LiveRoomId, 389 | &info.LiveRoomName, &info.LiveRoomDesc, &info.LiveRoomTopic, &info.LiveAnchorPwd, 390 | &info.LiveUserPwd, &info.PlayRtmpUrl, &info.PlayHlsUrl, &info.PlayFlvUrl); err != nil { 391 | logger.Error("DBGetAllLiveRoomList : ", err.Error()) 392 | resp.OfflineList = resp.OfflineList[:0] 393 | return lastIndex, err 394 | } 395 | info.FollowCount = DBGetFollowCount(info.LiveRoomId) 396 | info.IsFollow = 1 397 | logger.Info("DBGetAllLiveRoomList: info=", info) 398 | resp.OfflineList = append(resp.OfflineList, info) 399 | } 400 | if err = rows.Err(); err != nil { 401 | logger.Error("DBGetAllLiveRoomList : ", err.Error()) 402 | resp.OfflineList = resp.OfflineList[:0] 403 | return lastIndex, err 404 | } 405 | return lastuserId, nil 406 | } 407 | 408 | func DBUpdateLiveroomUrls(liveroomId int64, playRtmpUrls, playHlsUrls, playFlvUrls string) error { 409 | db := SP_MysqlDbPool.GetDBConn() 410 | _, err := db.Exec("UPDATE tbl_liverooms SET play_rtmp_urls=?, play_hls_urls=?, play_flv_urls=? WHERE liveroom_id=?", 411 | playRtmpUrls, playHlsUrls, playFlvUrls, liveroomId) 412 | 413 | if err != nil { 414 | logger.Error("DBUpdateLiveroomUrls : ", err.Error()) 415 | return err 416 | } 417 | logger.Info("DBUpdateLiveroomUrls : success. liveroomId=", liveroomId, ", playRtmpUrls=", playRtmpUrls, 418 | ", playHlsUrls=", playHlsUrls, ", playFlvUrls=", playFlvUrls) 419 | return nil 420 | } 421 | 422 | func DBGetLiveroomUrls(liveroomId int64) (playRtmpUrls, playHlsUrls, playFlvUrls string) { 423 | db := SP_MysqlDbPool.GetDBConn() 424 | 425 | err := db.QueryRow("SELECT play_rtmp_urls, play_hls_urls, play_flv_urls FROM tbl_liverooms WHERE liveroom_id=?", 426 | liveroomId).Scan(&playRtmpUrls, &playHlsUrls, &playFlvUrls) 427 | 428 | if err != nil { 429 | logger.Error("DBGetLiveroomUrls : ", err.Error()) 430 | return 431 | } 432 | 433 | logger.Info("DBGetLiveroomUrls : success. liveroomId=", liveroomId, ", playRtmpUrls=", playRtmpUrls, 434 | ", playHlsUrls=", playHlsUrls, ", playFlvUrls=", playFlvUrls) 435 | return 436 | } 437 | 438 | func DBGetLiveroomIds() []int64 { 439 | db := SP_MysqlDbPool.GetDBConn() 440 | rows, err := db.Query("SELECT liveroom_id FROM tbl_liverooms") 441 | if err != nil { 442 | logger.Error("DBGetLiveroomIds : query err=", err.Error()) 443 | return nil 444 | } 445 | defer rows.Close() 446 | 447 | var ( 448 | liveroomId int64 449 | liveroomIds []int64 450 | ) 451 | 452 | for rows.Next() { 453 | err = rows.Scan(&liveroomId) 454 | if err != nil { 455 | logger.Error("DBGetLiveroomIds : scan err=", err.Error()) 456 | return nil 457 | } 458 | liveroomIds = append(liveroomIds, liveroomId) 459 | } 460 | return liveroomIds 461 | } 462 | -------------------------------------------------------------------------------- /src/apiserver/service/dbUser.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "database/sql" 5 | "errors" 6 | "fmt" 7 | "gotye_protocol" 8 | "strings" 9 | 10 | "github.com/futurez/litego/logger" 11 | "github.com/futurez/litego/util" 12 | ) 13 | 14 | func DBCheckUserAccount(username, password string) (userId, headPicId int64, nickname string, sex int8, status_code int) { 15 | db := SP_MysqlDbPool.GetDBConn() 16 | var pwd string 17 | err := db.QueryRow("SELECT user_id, nickname, pwd, headpic_id, sex FROM tbl_users WHERE phone=? OR nickname=?", 18 | username, username).Scan(&userId, &nickname, &pwd, &headPicId, &sex) 19 | switch { 20 | case err == sql.ErrNoRows: 21 | logger.Infof("DBCheckUserAccount : %s not exists.", username) 22 | status_code = gotye_protocol.API_USERNAME_NOT_EXISTS_ERROR 23 | return 24 | case err != nil: 25 | logger.Error("DBCheckUserAccount : ", err.Error()) 26 | status_code = gotye_protocol.API_SERVER_ERROR 27 | return 28 | } 29 | 30 | if len(pwd) == 0 && len(password) == 0 { 31 | status_code = gotye_protocol.API_SUCCESS 32 | return 33 | } 34 | 35 | if pwd != util.Md5Hash(password) { 36 | logger.Infof("DBCheckUserAccount : %s password error", username) 37 | status_code = gotye_protocol.API_LOGIN_PASSWORD_ERROR 38 | return 39 | } 40 | status_code = gotye_protocol.API_SUCCESS 41 | return 42 | } 43 | 44 | func DBGetUserIdByNickname(nickname string) int64 { 45 | logger.Info("DBGetUserIdByNickname: nickname=", nickname) 46 | db := SP_MysqlDbPool.GetDBConn() 47 | var userId int64 48 | err := db.QueryRow("SELECT user_id FROM tbl_users WHERE nickname=?", nickname).Scan(&userId) 49 | if err != nil { 50 | logger.Error("DBGetUserIdByNickname : err=", err.Error()) 51 | return 0 52 | } 53 | return userId 54 | } 55 | 56 | func DBIsNicknameExists(nickname string) bool { 57 | logger.Info("DBIsAccountExists : nickname=", nickname) 58 | 59 | db := SP_MysqlDbPool.GetDBConn() 60 | var count int 61 | err := db.QueryRow("SELECT count(*) as count FROM tbl_users WHERE nickname=?", nickname).Scan(&count) 62 | switch { 63 | case err == sql.ErrNoRows: 64 | logger.Warn("DBIsPhoneExists : why not row.") 65 | case err != nil: 66 | logger.Error("DBIsAccountExists : ", err.Error()) 67 | } 68 | return count != 0 69 | } 70 | 71 | func DBIsPhoneExists(phone string) bool { 72 | logger.Info("DBIsPhoneExists : phone=", phone) 73 | 74 | db := SP_MysqlDbPool.GetDBConn() 75 | var count int 76 | err := db.QueryRow("SELECT count(*) as count FROM tbl_users WHERE phone=?", phone).Scan(&count) 77 | switch { 78 | case err == sql.ErrNoRows: 79 | logger.Warn("DBIsPhoneExists : why not row.") 80 | case err != nil: 81 | logger.Error("DBIsPhoneExists : ", err.Error()) 82 | } 83 | return count != 0 84 | } 85 | 86 | //create new user 87 | func DBCreateUserAccount(phone, passwd string) int64 { 88 | db := SP_MysqlDbPool.GetDBConn() 89 | res, err := db.Exec("INSERT INTO tbl_users(phone,nickname,pwd) VALUES(?,?,?)", phone, util.RandNickname(), util.Md5Hash(passwd)) 90 | if err != nil { 91 | logger.Error("DBCreateUserAccount : ", err.Error()) 92 | return -1 93 | } 94 | num, _ := res.LastInsertId() 95 | logger.Info("DBCreateUserAccount : LastInsertId=", num) 96 | return num 97 | } 98 | 99 | func DBModifyUserNickName(userid int64, nickname string) error { 100 | db := SP_MysqlDbPool.GetDBConn() 101 | res, err := db.Exec("UPDATE tbl_users SET nickname=? WHERE user_id=?", nickname, userid) 102 | if err != nil { 103 | logger.Error("DBModifyUserNickName : ", err.Error()) 104 | return err 105 | } 106 | num, _ := res.RowsAffected() 107 | logger.Info("DBModifyUserNickName : RowsAffected=", num) 108 | return nil 109 | } 110 | 111 | func DBModifyUserInfo(userid int64, sex int8, addr string) error { 112 | db := SP_MysqlDbPool.GetDBConn() 113 | var setValue []string 114 | if sex == 1 || sex == 2 { 115 | setValue = append(setValue, fmt.Sprintf("sex=%d", sex)) 116 | } 117 | if len(addr) > 0 { 118 | setValue = append(setValue, fmt.Sprintf("address='%s'", addr)) 119 | } 120 | setData := strings.Join(setValue, ",") 121 | sql := fmt.Sprintf("UPDATE tbl_users SET %s WHERE user_id=%d", setData, userid) 122 | logger.Info("DBModifyUserInfo : sql=", sql) 123 | 124 | res, err := db.Exec(sql) 125 | if err != nil { 126 | logger.Error("DBModifyUserInfo : ", err.Error()) 127 | return err 128 | } 129 | num, _ := res.RowsAffected() 130 | logger.Info("DBModifyUserInfo : RowsAffected=", num) 131 | return nil 132 | } 133 | 134 | func DBGetHeadPicIdByUserId(userid int64) int64 { 135 | db := SP_MysqlDbPool.GetDBConn() 136 | var headPicId int64 137 | err := db.QueryRow("SELECT headpic_id FROM tbl_users WHERE user_id=?", userid).Scan(&headPicId) 138 | switch { 139 | case err == sql.ErrNoRows: 140 | logger.Warn("DBGetHeadPicIdByUserId : why not row.") 141 | case err != nil: 142 | logger.Errorf("DBGetHeadPicIdByUserId : userid=%d, err=%s", userid, err.Error()) 143 | default: 144 | logger.Infof("DBGetHeadPicIdByUserId : user_id=%d, headPicId=%d.", userid, headPicId) 145 | } 146 | return headPicId 147 | } 148 | 149 | func DBUpdateHeadPicIdByUserId(userId, headPicId int64) error { 150 | db := SP_MysqlDbPool.GetDBConn() 151 | res, err := db.Exec("UPDATE tbl_users SET headpic_id=? WHERE user_id=?", headPicId, userId) 152 | if err != nil { 153 | logger.Error("DBUpdateHeadPicIdByUserId : ", err.Error()) 154 | return err 155 | } 156 | num, _ := res.RowsAffected() 157 | logger.Info("DBUpdateHeadPicIdByUserId : RowsAffected=", num) 158 | return nil 159 | } 160 | 161 | func DBModifyUserHeadPic(userId int64, headPic []byte) (int64, error) { 162 | headPicId := DBGetHeadPicIdByUserId(userId) 163 | db := SP_MysqlDbPool.GetDBConn() 164 | if headPicId == 0 { 165 | //add new headPic 166 | res, err := db.Exec("INSERT INTO tbl_pictures(pic) VALUES(?)", headPic) 167 | if err != nil { 168 | logger.Error("DBModifyUserHeadPic : insert into tbl_pictures failed. ", err.Error()) 169 | return 0, err 170 | } 171 | num, err := res.LastInsertId() 172 | if err != nil { 173 | logger.Error("DBModifyUserHeadPic : get lastinertid failed. ", err.Error()) 174 | return 0, err 175 | } 176 | logger.Info("DBModifyUserHeadPic : insert LastInsertId=", num) 177 | err = DBUpdateHeadPicIdByUserId(userId, num) 178 | if err != nil { 179 | logger.Error("DBModifyUserHeadPic : err=", err.Error()) 180 | return 0, err 181 | } 182 | return num, nil 183 | } else { 184 | res, err := db.Exec("UPDATE tbl_pictures SET pic=? WHERE pic_id=?", headPic, headPicId) 185 | if err != nil { 186 | logger.Error("DBModifyUserHeadPic : update tbl_pictures failed, ", err.Error()) 187 | return headPicId, err 188 | } 189 | num, _ := res.RowsAffected() 190 | logger.Info("DBModifyUserHeadPic : Update RowsAffected=", num) 191 | return headPicId, nil 192 | } 193 | } 194 | 195 | func DBModifyUserPwd(phone, pwd string) error { 196 | db := SP_MysqlDbPool.GetDBConn() 197 | res, err := db.Exec("UPDATE tbl_users SET pwd=? WHERE phone=?", util.Md5Hash(pwd), phone) 198 | if err != nil { 199 | logger.Error("DBModifyUserPwd : update tbl_pictures failed, ", err.Error()) 200 | return err 201 | } 202 | num, _ := res.RowsAffected() 203 | logger.Info("DBModifyUserPwd : RowsAffected=", num) 204 | if num == 1 { 205 | return nil 206 | } else { 207 | return errors.New("not exist phone") 208 | } 209 | } 210 | 211 | func DBGetUserHeadPic(picId int64) ([]byte, error) { 212 | db := SP_MysqlDbPool.GetDBConn() 213 | var pic []byte 214 | err := db.QueryRow("SELECT pic FROM tbl_pictures WHERE pic_id=?", picId).Scan(&pic) 215 | switch { 216 | case err == sql.ErrNoRows: 217 | logger.Warn("DBGetUserHeadPic : why not row, picId=", picId) 218 | return nil, err 219 | case err != nil: 220 | logger.Error("DBGetUserHeadPic : ", err.Error()) 221 | return nil, err 222 | default: 223 | logger.Info("DBGetUserHeadPic : success get pic_id=", picId) 224 | } 225 | return pic, nil 226 | } 227 | -------------------------------------------------------------------------------- /src/apiserver/service/gotyeRequestApi.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "gotye_protocol/gotye_sdk" 5 | "strconv" 6 | "sync" 7 | "time" 8 | 9 | "github.com/futurez/litego/httplib" 10 | "github.com/futurez/litego/logger" 11 | "github.com/futurez/litego/util" 12 | ) 13 | 14 | type TokenCache struct { 15 | sync.RWMutex 16 | accessToken string 17 | expires time.Time 18 | bValid bool 19 | } 20 | 21 | func (t *TokenCache) GetAccessToken() (string, bool) { 22 | t.RLock() 23 | defer t.RUnlock() 24 | 25 | if !t.bValid { 26 | return "", false 27 | } 28 | 29 | if t.expires.After(time.Now()) { 30 | logger.Infof("AccessAppToken : quick accessToken=%s", t.accessToken) 31 | return t.accessToken, true 32 | } 33 | return "", false 34 | } 35 | 36 | func (t *TokenCache) SetAccessToken(token string, expire int64) { 37 | t.Lock() 38 | defer t.Unlock() 39 | 40 | t.accessToken = token 41 | //before 60s accessAppToken 42 | t.expires = time.Now().Add(time.Second * time.Duration(expire-60)) 43 | t.bValid = true 44 | } 45 | 46 | func (t *TokenCache) ResetAccessToken() { 47 | t.Lock() 48 | defer t.Unlock() 49 | 50 | t.bValid = false 51 | t.accessToken = "" 52 | } 53 | 54 | var SP_tokenCache = &TokenCache{} 55 | 56 | func GotyeClearAccessToken() { 57 | SP_tokenCache.ResetAccessToken() 58 | } 59 | 60 | func GotyeAccessAppToken() (string, error) { 61 | if token, ok := SP_tokenCache.GetAccessToken(); ok { 62 | return token, nil 63 | } 64 | 65 | //send request. 66 | req := gotye_sdk.AccessTokenAppRequest{} 67 | req.Scope = "app" 68 | req.UserName = SP_appInfo.username 69 | req.Password = SP_appInfo.password 70 | resp := gotye_sdk.AccessTokenResponse{} 71 | 72 | logger.Info("GotyeAccessAppToken : req=", req) 73 | err := httplib.HttpRequestJson(gotye_sdk.HttpUrlAccessToken, &req, &resp) 74 | if err != nil { 75 | logger.Error("GotyeAccessAppToken : ", err.Error()) 76 | return "", err 77 | } 78 | logger.Info("GotyeAccessAppToken : resp=", resp) 79 | SP_tokenCache.SetAccessToken(resp.AccessToken, resp.ExpiresIn) 80 | return resp.AccessToken, nil 81 | } 82 | 83 | func GotyeAccessRoomToken(liveRoomId int64, password, nickname string) (string, error) { 84 | //send request. 85 | req := gotye_sdk.AccessTokenRoomRequest{} 86 | req.Scope = "room" 87 | req.RoomId = liveRoomId 88 | req.Password = password 89 | req.NickName = nickname 90 | req.SecretKey = util.Md5Hash(strconv.FormatInt(liveRoomId, 10) + password + SP_appInfo.accessSecret) 91 | 92 | resp := gotye_sdk.AccessTokenResponse{} 93 | 94 | logger.Info("GotyeAccessRoomToken : ", req) 95 | err := httplib.HttpRequestJson(gotye_sdk.HttpUrlAccessToken, &req, &resp) 96 | if err != nil { 97 | logger.Error("GotyeAccessRoomToken : ", err.Error()) 98 | return "", err 99 | } 100 | logger.Info("GotyeAccessRoomToken : ", resp) 101 | return resp.AccessToken, nil 102 | } 103 | 104 | func GotyeCreateRoom(roomName, anchorPwd, assistPwd, userPwd, anchorDesc, 105 | contentDesc string) (*gotye_sdk.CreateRoomResponse, error) { 106 | 107 | resp := gotye_sdk.CreateRoomResponse{} 108 | req := gotye_sdk.CreateRoomRequest{} 109 | req.RoomName = roomName 110 | req.AnchorPwd = anchorPwd 111 | req.AssistPwd = assistPwd 112 | req.UserPwd = userPwd 113 | req.AnchorDesc = anchorDesc 114 | req.ContentDesc = contentDesc 115 | 116 | headers := map[string]string{} 117 | 118 | bAgain := false 119 | LabelAgain: 120 | 121 | apptoken, err := GotyeAccessAppToken() 122 | if err != nil { 123 | logger.Error("ModifyMyLiveRoom : AccessToken Failed, ", err.Error()) 124 | return nil, err 125 | } 126 | 127 | headers["Authorization"] = apptoken 128 | logger.Info("GotyeCreateRoom : req=", req) 129 | err = httplib.HttpRequestJsonToken(gotye_sdk.HttpUrlCreateRoom, headers, req, &resp) 130 | if err != nil { 131 | logger.Error("GotyeCreateRoom : ", err.Error()) 132 | return nil, err 133 | } 134 | 135 | if !bAgain && resp.Status == gotye_sdk.API_INVALID_TOKEN_ERROR { 136 | GotyeClearAccessToken() 137 | logger.Info("ModifyMyLiveRoom : invalid token error, and accesstoken again.") 138 | bAgain = true 139 | goto LabelAgain 140 | } 141 | 142 | logger.Info("GotyeCreateRoom : resp=", resp) 143 | return &resp, nil 144 | } 145 | 146 | func GotyeModifyRoom(roomId int64, roomName, anchorPwd, assistPwd, userPwd, anchorDesc, contentDesc string) int { 147 | resp := gotye_sdk.ModifyRoomResponse{} 148 | req := make(map[string]interface{}) 149 | req["roomId"] = roomId 150 | req["enableRecordFlag"] = 1 151 | req["permanentPlayFlag"] = 1 152 | req["startPlayTime"] = time.Now().Second() 153 | if len(roomName) > 0 { 154 | req["roomName"] = roomName 155 | } 156 | if len(anchorPwd) > 0 { 157 | req["anchorPwd"] = anchorPwd 158 | } 159 | if len(assistPwd) > 0 { 160 | req["assistPwd"] = assistPwd 161 | } 162 | if len(userPwd) > 0 { 163 | req["userPwd"] = userPwd 164 | } 165 | if len(anchorDesc) > 0 { 166 | req["anchorDesc"] = anchorDesc 167 | } 168 | if len(contentDesc) > 0 { 169 | req["contentDesc"] = contentDesc 170 | } 171 | 172 | headers := map[string]string{} 173 | 174 | bAgain := false 175 | LabelAgain: 176 | 177 | apptoken, err := GotyeAccessAppToken() 178 | if err != nil { 179 | logger.Error("GotyeModifyRoom : AccessToken Failed, ", err.Error()) 180 | return -1 181 | } 182 | 183 | headers["Authorization"] = apptoken 184 | 185 | logger.Info("GotyeModifyRoom : req=", req) 186 | err = httplib.HttpRequestJsonToken(gotye_sdk.HttpUrlModifyRoom, headers, req, &resp) 187 | if err != nil { 188 | logger.Error("GotyeModifyRoom : ", err.Error()) 189 | return -1 190 | } 191 | 192 | if !bAgain && resp.Status == gotye_sdk.API_INVALID_TOKEN_ERROR { 193 | GotyeClearAccessToken() 194 | logger.Info("GotyeModifyRoom : invalid token error, and accesstoken again.") 195 | bAgain = true 196 | goto LabelAgain 197 | } 198 | 199 | logger.Info("GotyeModifyRoom : resp=", resp) 200 | return resp.Status 201 | } 202 | 203 | func GotyeGetLiveContext(roomId int64) (int, int, error) { 204 | req := gotye_sdk.GetLiveContextRequest{RoomId: roomId} 205 | resp := gotye_sdk.GetLiveContextResponse{} 206 | 207 | headers := map[string]string{} 208 | logger.Info("GotyeGetLiveContext : req=", req) 209 | 210 | bAgain := false 211 | LabelAgain: 212 | 213 | apptoken, err := GotyeAccessAppToken() 214 | if err != nil { 215 | logger.Error("GotyeModifyRoom : AccessToken Failed, ", err.Error()) 216 | return 0, 0, err 217 | } 218 | 219 | headers["Authorization"] = apptoken 220 | 221 | err = httplib.HttpRequestJsonToken(gotye_sdk.HttpGetLiveContext, headers, req, &resp) 222 | if err != nil { 223 | logger.Error("GotyeGetLiveContext : ", err.Error()) 224 | return 0, 0, err 225 | } 226 | 227 | if !bAgain && resp.Status == gotye_sdk.API_INVALID_TOKEN_ERROR { 228 | GotyeClearAccessToken() 229 | logger.Info("GotyeGetLiveContext : invalid token error, and accesstoken again.") 230 | bAgain = true 231 | goto LabelAgain 232 | } 233 | 234 | logger.Info("GotyeGetLiveContext : resp=", resp) 235 | return resp.Entity.PlayUserCount, resp.Status, nil 236 | } 237 | 238 | func GotyeGetRoomsLiveInfo(roomIds ...int64) (*gotye_sdk.GetRoomsLiveInfoResponse, error) { 239 | resp := gotye_sdk.GetRoomsLiveInfoResponse{} 240 | req := gotye_sdk.GetRoomsLiveInfoRequest{roomIds} 241 | headers := map[string]string{} 242 | 243 | logger.Info("GotyeGetRoomsLiveInfo : req=", req) 244 | 245 | bAgain := false 246 | LabelAgain: 247 | 248 | apptoken, err := GotyeAccessAppToken() 249 | if err != nil { 250 | logger.Error("GotyeGetRoomsLiveInfo : AccessToken Failed, ", err.Error()) 251 | return nil, err 252 | } 253 | 254 | headers["Authorization"] = apptoken 255 | 256 | err = httplib.HttpRequestJsonToken(gotye_sdk.HttpGetRoomsLiveInfo, headers, req, &resp) 257 | if err != nil { 258 | logger.Error("GotyeGetRoomsLiveInfo : ", err.Error()) 259 | return nil, err 260 | } 261 | 262 | if !bAgain && resp.Status == gotye_sdk.API_INVALID_TOKEN_ERROR { 263 | GotyeClearAccessToken() 264 | logger.Info("GotyeGetRoomsLiveInfo : invalid token error, and accesstoken again.") 265 | bAgain = true 266 | goto LabelAgain 267 | } 268 | 269 | logger.Info("GotyeGetRoomsLiveInfo : resp=", resp) 270 | return &resp, nil 271 | } 272 | 273 | func GotyeGetLiveroomUrl(roomId int64) (playRtmlUrl, playHlsUrl, playFlvUrl string) { 274 | logger.Debug("GotyeGetLiveroomUrl : liveroomId=", roomId) 275 | resp, err := GotyeGetRoomsLiveInfo(roomId) 276 | if err != nil { 277 | logger.Error("GotyeGetLiveroomUrl : err=", err.Error()) 278 | return 279 | } 280 | 281 | if resp.Status != gotye_sdk.API_SUCCESS || len(resp.Entities) == 0 { 282 | logger.Error("CreateLiveRoom : GotyeGetLiveContext status=", resp.Status) 283 | return 284 | } 285 | 286 | if len(resp.Entities[0].PlayRtmpUrls) > 0 { 287 | playRtmlUrl = resp.Entities[0].PlayRtmpUrls[0] 288 | } 289 | 290 | if len(resp.Entities[0].PlayHlsUrls) > 0 { 291 | playHlsUrl = resp.Entities[0].PlayHlsUrls[0] 292 | } 293 | 294 | if len(resp.Entities[0].PlayFlvUrls) > 0 { 295 | playFlvUrl = resp.Entities[0].PlayFlvUrls[0] 296 | } 297 | return 298 | } 299 | -------------------------------------------------------------------------------- /src/apiserver/service/gotyeRequestApi_test.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "gotye_protocol/gotye_sdk" 5 | "testing" 6 | ) 7 | 8 | func TestGotyeGetRoomsLiveInfo(t *testing.T) { 9 | InitMysqlDbPool("192.168.1.141", "gotye_open_live", "appuser", "123456") 10 | 11 | ids := []int64{210336} 12 | 13 | //get live room play urls. 14 | liveInfo, err := GotyeGetRoomsLiveInfo(ids...) 15 | if err != nil { 16 | t.Error("CreateLiveRoom : ", err.Error()) 17 | return 18 | } 19 | if liveInfo.Status != gotye_sdk.API_SUCCESS || len(liveInfo.Entities) == 0 { 20 | t.Error("CreateLiveRoom : GotyeGetLiveContext status=", liveInfo.Status) 21 | return 22 | } 23 | 24 | // //insert to tbl_liveroom_urls 25 | // for _, entity := range liveInfo.Entities { 26 | // err = DBInsertLiveroomUrls(entity.RoomId, entity.PlayRtmpUrls, entity.PlayHlsUrls, entity.PlayFlvUrls) 27 | // if err != nil { 28 | // logger.Error("CreateLiveRoom : ", err.Error()) 29 | // } 30 | // } 31 | } 32 | -------------------------------------------------------------------------------- /src/apiserver/service/liveroom.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "gotye_protocol" 5 | "gotye_protocol/gotye_sdk" 6 | 7 | "github.com/futurez/litego/logger" 8 | ) 9 | 10 | const ( 11 | DefaultAnchorPwd = "anchorpwd" 12 | DefaultAssistPwd = "assistpwd" 13 | DefaultUserPwd = "userpwd" 14 | ) 15 | 16 | func CreateLiveRoom(resp *gotye_protocol.CreateLiveRoomResponse, 17 | req *gotye_protocol.CreateLiveRoomRequest) { 18 | 19 | sd, ok := SP_sessionMgr.readSession(req.SessionID) 20 | if !ok { 21 | resp.SetStatus(gotye_protocol.API_EXPIRED_SESSION_ERROR) 22 | logger.Info("CreateLiveRoom : get session data failed.") 23 | return 24 | } 25 | sd.UpdateTick() 26 | 27 | //check is have liveroom_id 28 | if sd.liveroom_id != 0 { 29 | resp.SetStatus(gotye_protocol.API_SUCCESS) 30 | resp.LiveRoomId = sd.liveroom_id 31 | logger.Warn("CreateLiveRoom : already have liveroom_id=", resp.LiveRoomId) 32 | return 33 | } 34 | 35 | //check three password 36 | if len(req.LiveAnchorPwd) == 0 { 37 | req.LiveAnchorPwd = DefaultAnchorPwd 38 | } 39 | if len(req.LiveAssistPwd) == 0 { 40 | req.LiveAssistPwd = DefaultAssistPwd 41 | } 42 | if len(req.LiveUserPwd) == 0 { 43 | req.LiveUserPwd = DefaultUserPwd 44 | } 45 | 46 | // create live room 47 | result, err := GotyeCreateRoom(req.LiveRoomName, req.LiveAnchorPwd, req.LiveAssistPwd, 48 | req.LiveUserPwd, req.LiveRoomDesc, req.LiveRoomTopic) 49 | if err != nil { 50 | logger.Error("CreateLiveRoom : create room error=", err.Error()) 51 | resp.SetStatus(gotye_protocol.API_SERVER_ERROR) 52 | return 53 | } 54 | if result.Status != gotye_sdk.API_SUCCESS { 55 | logger.Error("CreateLiveRoom : failed, status=", result.Status) 56 | resp.SetStatus(gotye_protocol.API_SERVER_ERROR) 57 | return 58 | } 59 | //get live room play urls. 60 | playRtmpUrl, playHlsUrl, playFlvUrl := GotyeGetLiveroomUrl(result.Entity.RoomId) 61 | 62 | //insert to tbl_liverooms 63 | err = DBCreateLiveroom(sd.user_id, result.Entity.RoomId, result.Entity.RoomName, result.Entity.AnchorDesc, 64 | result.Entity.ContentDesc, result.Entity.AnchorPwd, result.Entity.AssistPwd, result.Entity.UserPwd, 65 | playRtmpUrl, playHlsUrl, playFlvUrl) 66 | if err != nil { 67 | logger.Error("CreateLiveRoom : ", err.Error()) 68 | resp.SetStatus(gotye_protocol.API_SERVER_ERROR) 69 | return 70 | } 71 | 72 | sd.liveroom_id = result.Entity.RoomId 73 | resp.LiveRoomId = result.Entity.RoomId 74 | resp.SetStatus(gotye_protocol.API_SUCCESS) 75 | logger.Info("CreateLiveRoom : success create liveroom_id= ", result.Entity.RoomId) 76 | } 77 | 78 | func ModifyMyLiveRoom(resp *gotye_protocol.ModifyMyLiveRoomResponse, 79 | req *gotye_protocol.ModifyMyLiveRoomRequest) { 80 | 81 | sd, ok := SP_sessionMgr.readSession(req.SessionID) 82 | if !ok { 83 | resp.SetStatus(gotye_protocol.API_EXPIRED_SESSION_ERROR) 84 | logger.Info("ModifyMyLiveRoom : get session data failed.") 85 | return 86 | } 87 | sd.UpdateTick() 88 | 89 | if req.LiveRoomID == 0 { 90 | req.LiveRoomID = sd.liveroom_id 91 | } 92 | 93 | if sd.liveroom_id == 0 || req.LiveRoomID != sd.liveroom_id { 94 | resp.SetFormatStatus(gotye_protocol.API_PARAM_ERROR, "why liveroomid not equal.") 95 | logger.Warnf("ModifyMyLiveRoom : sd.liveroom_id=%d, req.liveroom_id=%d.", sd.liveroom_id, req.LiveRoomID) 96 | return 97 | } 98 | 99 | status := GotyeModifyRoom(req.LiveRoomID, req.LiveRoomName, 100 | req.LiveRoomAnchorPwd, DefaultAssistPwd, req.LiveUserPwd, req.LiveRoomDesc, req.LiveRoomTopic) 101 | 102 | switch status { 103 | case gotye_sdk.API_SUCCESS: 104 | { 105 | logger.Info("ModifyMyLiveRoom : success modify liveroom_id= .", req.LiveRoomID) 106 | err := DBModifyLiveRoomInfo(req.LiveRoomID, req.LiveRoomName, req.LiveRoomAnchorPwd, DefaultAssistPwd, 107 | req.LiveUserPwd, req.LiveRoomDesc, req.LiveRoomTopic) 108 | if err != nil { 109 | logger.Error("ModifyLiveRoom : ", err.Error()) 110 | resp.SetStatus(gotye_protocol.API_SERVER_ERROR) 111 | return 112 | } 113 | logger.Info("ModifyLiveRoom : Success.") 114 | resp.SetStatus(gotye_protocol.API_SUCCESS) 115 | return 116 | } 117 | 118 | case gotye_sdk.API_INVALID_LIVEROOM_ID_ERROR: 119 | fallthrough 120 | case gotye_sdk.API_NOT_EXISTS_LIVEROOM_ID_ERROR: 121 | logger.Error("ModifyMyLiveRoom : invalid liveroom_id =", req.LiveRoomID) 122 | resp.SetStatus(gotye_protocol.API_LIVEROOM_ID_NOT_EXIST_ERROR) 123 | return 124 | 125 | case gotye_sdk.API_REPECT_PASSWORD_LIVEROOM_ERROR: 126 | logger.Error("ModifyMyLiveRoom : repect anchor pwd =", req.LiveRoomAnchorPwd) 127 | resp.SetStatus(gotye_protocol.API_REPECT_PASSWORD_LIVEROOM_ERROR) 128 | return 129 | 130 | case gotye_sdk.API_INVALID_PASSWORD_LIVEROOM_ERROR: 131 | logger.Error("ModifyMyLiveRoom : invalid password =", req.LiveRoomAnchorPwd) 132 | resp.SetStatus(gotye_protocol.API_INVALID_PASSWORD_LIVEROOM_ERROR) 133 | return 134 | 135 | case gotye_sdk.API_INVALID_LIVEROOM_NAME_ERROR: 136 | logger.Error("ModifyMyLiveRoom : invalid roomName =", req.LiveRoomName) 137 | resp.SetStatus(gotye_protocol.API_INVALID_LIVEROOM_NAME_ERROR) 138 | return 139 | 140 | case gotye_sdk.API_NULL_LIVEROOM_ID_ERROR: 141 | logger.Error("ModifyMyLiveRoom : why null liveroom id =", req.LiveRoomID) 142 | resp.SetStatus(gotye_protocol.API_SERVER_ERROR) 143 | return 144 | 145 | default: 146 | logger.Error("CreateLiveRoom : unknown status=%d", status) 147 | resp.SetStatus(gotye_protocol.API_SERVER_ERROR) 148 | return 149 | } 150 | } 151 | 152 | func FollowLiveRoom(sessionId string, liveRoomId int64, isFollow int) int { 153 | sd, ok := SP_sessionMgr.readSession(sessionId) 154 | if !ok { 155 | logger.Info("ModifyMyLiveRoom : get session data failed.") 156 | return gotye_protocol.API_EXPIRED_SESSION_ERROR 157 | } 158 | sd.UpdateTick() 159 | 160 | var err error 161 | if isFollow == 1 { 162 | err = DBAddFollowLiveRoom(sd.user_id, liveRoomId) 163 | } else { 164 | err = DBDelFollowLiveRoom(sd.user_id, liveRoomId) 165 | } 166 | if err != nil { 167 | return gotye_protocol.API_SERVER_ERROR 168 | } 169 | return gotye_protocol.API_SUCCESS 170 | } 171 | 172 | func PushingLiveStream(sessinId string, liveRoomId int64, Status int, Timeout int) int { 173 | sd, ok := SP_sessionMgr.readSession(sessinId) 174 | if !ok { 175 | logger.Warn("PushingLiveStream : get session data failed.") 176 | return gotye_protocol.API_EXPIRED_SESSION_ERROR 177 | } 178 | sd.UpdateTick() 179 | 180 | if liveRoomId != sd.liveroom_id { 181 | logger.Warnf("PushingLiveStream : why liveroomId(%d) != sd.liveroomId(%d).", liveRoomId, sd.liveroom_id) 182 | return gotye_protocol.API_LIVEROOM_ID_NOT_EXIST_ERROR 183 | } 184 | 185 | if Status == 1 { 186 | SP_onlineLiveMgr.StartPushStream(liveRoomId, Timeout) 187 | } else { 188 | SP_onlineLiveMgr.StopPushStream(liveRoomId) 189 | } 190 | return gotye_protocol.API_SUCCESS 191 | } 192 | 193 | func GetMyLiveRoom(resp *gotye_protocol.GetMyLiveRoomResponse, req *gotye_protocol.GetMyLiveRoomRequest) { 194 | sd, ok := SP_sessionMgr.readSession(req.SessionID) 195 | if !ok { 196 | logger.Info("GetMyLiveRoom : get session data failed.") 197 | resp.SetStatus(gotye_protocol.API_EXPIRED_SESSION_ERROR) 198 | return 199 | } 200 | sd.UpdateTick() 201 | 202 | if sd.liveroom_id == 0 { 203 | logger.Info("GetMyLiveRoom : nickname=", sd.nickname, "not exist liveroom") 204 | resp.SetStatus(gotye_protocol.API_LIVEROOM_NOT_EXISTS_ERROR) 205 | return 206 | } 207 | 208 | liveroomInfo, ok := DBGetLiveRoomByUserId(sd.user_id) 209 | if !ok { 210 | logger.Warnf("GetMyLiveRoom : why get user_id=%d liveroom_id=%d failed.", sd.user_id, sd.liveroom_id) 211 | resp.SetStatus(gotye_protocol.API_SERVER_ERROR) 212 | return 213 | } 214 | 215 | resp.LiveRoomId = liveroomInfo.LiveRoomId 216 | resp.LiveAnchorPwd = liveroomInfo.LiveAnchorPwd 217 | resp.LiveUserPwd = liveroomInfo.LiveUserPwd 218 | resp.LiveRoomName = liveroomInfo.LiveRoomName 219 | resp.LiveRoomDesc = liveroomInfo.LiveRoomDesc 220 | resp.LiveRoomTopic = liveroomInfo.LiveRoomTopic 221 | resp.AnchorName = liveroomInfo.AnchorName 222 | resp.PlayRtmpUrl = liveroomInfo.PlayRtmpUrl 223 | resp.PlayHlsUrl = liveroomInfo.PlayHlsUrl 224 | resp.PlayFlvUrl = liveroomInfo.PlayFlvUrl 225 | 226 | if resp.PlayRtmpUrl == "" || resp.PlayHlsUrl == "" || resp.PlayFlvUrl == "" { 227 | logger.Warn("GetMyLiveRoom : url is nil") 228 | resp.PlayRtmpUrl, resp.PlayHlsUrl, resp.PlayFlvUrl = GotyeGetLiveroomUrl(resp.LiveRoomId) 229 | DBUpdateLiveroomUrls(resp.LiveRoomId, resp.PlayRtmpUrl, resp.PlayHlsUrl, resp.PlayFlvUrl) 230 | } 231 | 232 | resp.FollowCount = DBGetFollowCount(sd.liveroom_id) 233 | resp.HeadPicId = DBGetHeadPicIdByUserId(sd.user_id) 234 | resp.AnchorName = sd.nickname 235 | resp.SetStatus(gotye_protocol.API_SUCCESS) 236 | return 237 | } 238 | 239 | func GetMyLiveRoomId(resp *gotye_protocol.GetMyLiveRoomIdResponse, req *gotye_protocol.GetMyLiveRoomIdRequest) { 240 | sd, ok := SP_sessionMgr.readSession(req.SessionID) 241 | if !ok { 242 | logger.Info("GetMyLiveRoom : get session data failed.") 243 | resp.SetStatus(gotye_protocol.API_EXPIRED_SESSION_ERROR) 244 | return 245 | } 246 | sd.UpdateTick() 247 | 248 | resp.LiveRoomId = sd.liveroom_id 249 | resp.SetStatus(gotye_protocol.API_SUCCESS) 250 | logger.Info("GetMyLiveRoomId : user_id=%d, liveroom_id=%d.", sd.user_id, sd.liveroom_id) 251 | } 252 | 253 | func PlayLiveStream(sessinId string, liveroomId int64, Status int) int { 254 | sd, ok := SP_sessionMgr.readSession(sessinId) 255 | if !ok { 256 | logger.Warn("PushingLiveStream : get session data failed.") 257 | return gotye_protocol.API_EXPIRED_SESSION_ERROR 258 | } 259 | sd.UpdateTick() 260 | 261 | if Status == 1 { 262 | SP_onlineLiveMgr.StartPlayStream(liveroomId) 263 | } else { 264 | SP_onlineLiveMgr.StopPlayStream(liveroomId) 265 | } 266 | return gotye_protocol.API_SUCCESS 267 | } 268 | 269 | func GetLiveroomNumber(sessinId string, liveroomId int64) (int, int) { 270 | sd, ok := SP_sessionMgr.readSession(sessinId) 271 | if !ok { 272 | logger.Warn("PushingLiveStream : get session data failed.") 273 | return 0, gotye_protocol.API_EXPIRED_SESSION_ERROR 274 | } 275 | sd.UpdateTick() 276 | 277 | return SP_onlineLiveMgr.GetPlayCount(liveroomId), gotye_protocol.API_SUCCESS 278 | } 279 | -------------------------------------------------------------------------------- /src/apiserver/service/liveroomList.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "gotye_protocol" 5 | 6 | "github.com/futurez/litego/logger" 7 | ) 8 | 9 | const ( 10 | DEFAULT_LIST_COUNT = 5 11 | ) 12 | 13 | func GetAllLiveRoomList(resp *gotye_protocol.GetAllLiveRoomListResponse, req *gotye_protocol.GetLiveRoomListRequest) { 14 | sd, ok := SP_sessionMgr.readSession(req.SessionID) 15 | if !ok { 16 | logger.Warn("GetLiveRoomList : get session data failed.") 17 | resp.SetStatus(gotye_protocol.API_EXPIRED_SESSION_ERROR) 18 | return 19 | } 20 | sd.UpdateTick() 21 | resp.Type = req.Type 22 | 23 | if req.Refresh == 1 { 24 | sd.allLastId = 0 25 | } 26 | 27 | if req.Count == 0 { 28 | req.Count = DEFAULT_LIST_COUNT 29 | } 30 | 31 | logger.Info("GetAllLiveRoomList start allLastId=", sd.allLastId) 32 | var err error 33 | sd.allLastId, err = DBGetAllLiveRoomList(resp, sd.allLastId, req.Count) 34 | if err != nil { 35 | resp.SetStatus(gotye_protocol.API_SERVER_ERROR) 36 | return 37 | } else { 38 | resp.SetStatus(gotye_protocol.API_SUCCESS) 39 | } 40 | logger.Info("GetAllLiveRoomList end allLastId=", sd.allLastId) 41 | for i := range resp.List { 42 | resp.List[i].IsFollow = DBIsFollowLiveRoom(sd.user_id, resp.List[i].LiveRoomId) 43 | resp.List[i].PlayerCount = SP_onlineLiveMgr.GetPlayCount(resp.List[i].LiveRoomId) 44 | } 45 | } 46 | 47 | func GetFcousLiveRoomList(resp *gotye_protocol.GetFcousLiveRoomListResponse, req *gotye_protocol.GetLiveRoomListRequest) { 48 | sd, ok := SP_sessionMgr.readSession(req.SessionID) 49 | if !ok { 50 | logger.Warn("GetLiveRoomList : get session data failed.") 51 | resp.SetStatus(gotye_protocol.API_EXPIRED_SESSION_ERROR) 52 | return 53 | } 54 | sd.UpdateTick() 55 | resp.Type = req.Type 56 | 57 | if req.Refresh == 1 { 58 | sd.fcousLastId = 0 59 | sd.bfcousOnline = true 60 | } 61 | 62 | count := req.Count 63 | if count == 0 { 64 | count = DEFAULT_LIST_COUNT 65 | } 66 | 67 | var err error 68 | if sd.bfcousOnline { 69 | logger.Info("GetFcousLiveRoomList : get online fcous list, nickname=", sd.nickname) 70 | sd.fcousLastId, err = DBGetOnlineFocusLiveRoomList(resp, sd.user_id, sd.fcousLastId, count) 71 | if err != nil { 72 | resp.SetStatus(gotye_protocol.API_SERVER_ERROR) 73 | logger.Warn("GetFcousLiveRoomList : online list, err=", err.Error()) 74 | return 75 | } else { 76 | resp.SetStatus(gotye_protocol.API_SUCCESS) 77 | 78 | for i := range resp.OnlineList { 79 | resp.OnlineList[i].PlayerCount = SP_onlineLiveMgr.GetPlayCount(resp.OnlineList[i].LiveRoomId) 80 | } 81 | 82 | if len(resp.OnlineList) >= count { 83 | logger.Infof("GetFcousLiveRoomList : get online list full, nickname=%s, len=%d", sd.nickname, len(resp.OnlineList)) 84 | return 85 | } else { 86 | logger.Infof("GetFcousLiveRoomList : get online finished. and start get offline list.") 87 | sd.fcousLastId = 0 88 | count -= len(resp.OnlineList) 89 | sd.bfcousOnline = false 90 | } 91 | } 92 | } 93 | logger.Infof("GetFcousLiveRoomList : start get offline") 94 | 95 | sd.fcousLastId, err = DBGetOfflineFocusLiveRoomList(resp, sd.user_id, sd.fcousLastId, count) 96 | if err != nil { 97 | resp.SetStatus(gotye_protocol.API_SERVER_ERROR) 98 | logger.Warn("GetFcousLiveRoomList : online list, err=", err.Error()) 99 | return 100 | } else { 101 | resp.SetStatus(gotye_protocol.API_SUCCESS) 102 | } 103 | logger.Infof("GetFcousLiveRoomList : nickname=%s, onlineLen=%d, offlineLen=%d", sd.nickname, len(resp.OnlineList), len(resp.OfflineList)) 104 | } 105 | -------------------------------------------------------------------------------- /src/apiserver/service/liveroomSearch.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "gotye_protocol" 5 | "strconv" 6 | 7 | "github.com/futurez/litego/logger" 8 | ) 9 | 10 | func LiveRoomSearch(resp *gotye_protocol.SearchLiveStreamResponse, sessionId, keyword string) { 11 | sd, ok := SP_sessionMgr.readSession(sessionId) 12 | if !ok { 13 | logger.Warn("LiveRoomSearch : get session data failed.") 14 | resp.SetStatus(gotye_protocol.API_EXPIRED_SESSION_ERROR) 15 | return 16 | } 17 | sd.UpdateTick() 18 | logger.Infof("LiveRoomSearch : sessionId=%s, keyword=%s", sessionId, keyword) 19 | 20 | liveroomId, err := strconv.Atoi(keyword) 21 | if err != nil { 22 | logger.Warnf("LiveRoomSearch : keyword=%d, err=%s", keyword, err.Error()) 23 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 24 | return 25 | } 26 | 27 | err = DBGetLiveRoomByLiveroomId(resp, int64(liveroomId)) 28 | if err != nil { 29 | logger.Warn("LiveRoomSearch : keyword=", keyword) 30 | resp.SetStatus(gotye_protocol.API_LIVEROOM_ID_NOT_EXIST_ERROR) 31 | return 32 | } 33 | resp.FollowCount = DBGetFollowCount(resp.LiveRoomId) 34 | resp.IsFollow = DBIsFollowLiveRoom(sd.user_id, resp.LiveRoomId) 35 | resp.IsPlay = DBIsOnlineLiveRoom(resp.LiveRoomId) 36 | resp.SetStatus(gotye_protocol.API_SUCCESS) 37 | return 38 | } 39 | -------------------------------------------------------------------------------- /src/apiserver/service/onlineLiveManager.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "gotye_protocol/gotye_sdk" 5 | "sync" 6 | "time" 7 | 8 | "github.com/futurez/litego/logger" 9 | ) 10 | 11 | const ( 12 | LimitTimeOut = time.Minute * 1 13 | LimitPushTime = time.Minute * 1 14 | PreRefreshNum = 20 15 | ) 16 | 17 | type onlineLiveroom struct { 18 | liveroomId int64 19 | playerNum int 20 | needup int8 21 | } 22 | 23 | type OnlineLive struct { 24 | liveRoomId int64 25 | tick time.Time 26 | limit time.Duration 27 | playUserCount int 28 | bUp bool 29 | } 30 | 31 | type OnlineLiveManager struct { 32 | sync.RWMutex 33 | wg sync.WaitGroup 34 | liveMap map[int64]*OnlineLive 35 | } 36 | 37 | var SP_onlineLiveMgr = &OnlineLiveManager{liveMap: make(map[int64]*OnlineLive)} 38 | 39 | func init() { 40 | time.AfterFunc(LimitTimeOut, func() { SP_onlineLiveMgr.GC() }) 41 | } 42 | 43 | func (om *OnlineLiveManager) GC() { 44 | var inactiveIds []int64 45 | var activeIds []int64 46 | now := time.Now() 47 | 48 | om.RLock() 49 | for id, online := range om.liveMap { 50 | if !online.bUp { 51 | continue 52 | } 53 | 54 | if now.Sub(online.tick) > online.limit { 55 | inactiveIds = append(inactiveIds, id) 56 | } else { 57 | activeIds = append(activeIds, id) 58 | } 59 | } 60 | om.RUnlock() 61 | 62 | go func() { 63 | om.Lock() 64 | for _, id := range inactiveIds { 65 | logger.Debug("GC : Overdue liveroom_id = ", id) 66 | delete(om.liveMap, id) 67 | DBDelOnlineLiveRoom(id) 68 | } 69 | om.Unlock() 70 | }() 71 | 72 | total := len(activeIds) 73 | if total > 0 { 74 | limit := (total + PreRefreshNum) / PreRefreshNum * PreRefreshNum 75 | logger.Debug("GC : actvieIds=", activeIds, ",total=", total, ",limit=", limit) 76 | 77 | for i := 0; i < limit; i += PreRefreshNum { 78 | 79 | var ids []int64 80 | 81 | if i != (limit - PreRefreshNum) { 82 | ids = activeIds[i : i+PreRefreshNum] 83 | logger.Debug("GC : last i=", i, ",ids=", ids) 84 | } else { 85 | ids = activeIds[i:total] 86 | logger.Debug("GC : pre i=", i, ",ids=", ids) 87 | } 88 | 89 | om.wg.Add(1) 90 | go func(ids []int64) { 91 | defer om.wg.Done() 92 | 93 | resp, err := GotyeGetRoomsLiveInfo(ids...) 94 | if err != nil { 95 | logger.Error("UpdateNum : GotyeGetLiveContext Failed, ", err.Error()) 96 | return 97 | } 98 | 99 | if resp.Status == gotye_sdk.API_SUCCESS { 100 | om.UpStreamInfo(resp.Entities) 101 | } else { 102 | logger.Error("UpdateNum : GotyeGetLiveContext status=", resp.Status) 103 | } 104 | 105 | }(ids) 106 | } 107 | om.wg.Wait() 108 | } 109 | 110 | time.AfterFunc(LimitTimeOut, func() { om.GC() }) 111 | } 112 | 113 | func (om *OnlineLiveManager) UpStreamInfo(entities []gotye_sdk.LiveRoomInfo) { 114 | om.Lock() 115 | defer om.Unlock() 116 | 117 | for _, entity := range entities { 118 | online, ok := om.liveMap[entity.RoomId] 119 | if !ok { 120 | continue 121 | } 122 | online.playUserCount = entity.PlayUserCount 123 | DBUpdateOnlineLiveRoom(online.liveRoomId, online.playUserCount) 124 | } 125 | } 126 | 127 | func (om *OnlineLiveManager) LoadOnlineLiverooms() { 128 | om.Lock() 129 | defer om.Unlock() 130 | 131 | liverooms := DBReloadOnlineLiveroom() 132 | if liverooms == nil { 133 | logger.Info("LoadOnlineLiverooms : nil") 134 | return 135 | } 136 | 137 | for _, room := range *liverooms { 138 | online := &OnlineLive{} 139 | online.liveRoomId = room.liveroomId 140 | online.playUserCount = room.playerNum 141 | online.bUp = (room.needup == 1) 142 | online.limit = LimitPushTime 143 | online.tick = time.Now() 144 | om.liveMap[online.liveRoomId] = online 145 | logger.Info("LoadOnlineLiverooms : liveroomId=", online.liveRoomId, ",limit=", online.limit.Seconds(), "s,up=", online.bUp) 146 | } 147 | } 148 | 149 | func ReloadOnlineLiverooms() { 150 | SP_onlineLiveMgr.LoadOnlineLiverooms() 151 | } 152 | 153 | func (om *OnlineLiveManager) StartPushStream(liveroomId int64, limit int) { 154 | om.Lock() 155 | defer om.Unlock() 156 | 157 | online, ok := om.liveMap[liveroomId] 158 | if ok { 159 | logger.Info("StartPushStream : update liveroomid=", liveroomId) 160 | online.tick = time.Now() 161 | return 162 | } 163 | 164 | limitTime := LimitPushTime 165 | if limit > 0 { 166 | limitTime = time.Second * time.Duration(limit) 167 | } 168 | online = &OnlineLive{} 169 | online.liveRoomId = liveroomId 170 | online.tick = time.Now() 171 | online.limit = limitTime 172 | online.playUserCount = 0 173 | online.bUp = true 174 | 175 | om.liveMap[liveroomId] = online 176 | 177 | logger.Infof("StartPushStream : start liveroomId=%d,limit=%s", online.liveRoomId, online.limit) 178 | DBAddOnlineLiveRoom(liveroomId) 179 | } 180 | 181 | func (om *OnlineLiveManager) StopPushStream(liveroomId int64) { 182 | om.Lock() 183 | defer om.Unlock() 184 | 185 | _, ok := om.liveMap[liveroomId] 186 | if !ok { 187 | logger.Warn("StopPushStream : not found liveroomid=", liveroomId) 188 | return 189 | } 190 | logger.Info("StopPushStream : liveroomid=", liveroomId) 191 | delete(om.liveMap, liveroomId) 192 | DBDelOnlineLiveRoom(liveroomId) 193 | } 194 | 195 | func (om *OnlineLiveManager) GetPlayCount(liveroomId int64) int { 196 | om.RLock() 197 | defer om.RUnlock() 198 | 199 | liveroom, ok := om.liveMap[liveroomId] 200 | if !ok { 201 | logger.Warn("GetPlayCount : not found liveroomid=", liveroomId) 202 | return 0 203 | } 204 | return liveroom.playUserCount 205 | } 206 | 207 | func (om *OnlineLiveManager) StartPlayStream(liveroomId int64) { 208 | om.Lock() 209 | defer om.Unlock() 210 | 211 | liveroom, ok := om.liveMap[liveroomId] 212 | if !ok { 213 | logger.Warn("StartPlayStream : not found liveroomid=", liveroomId) 214 | return 215 | } 216 | 217 | liveroom.playUserCount++ 218 | DBUpdateOnlineLiveRoom(liveroom.liveRoomId, liveroom.playUserCount) 219 | 220 | logger.Info("StartPlayStream : liveroomid=", liveroomId, ", playnum=", liveroom.playUserCount) 221 | } 222 | 223 | func (om *OnlineLiveManager) StopPlayStream(liveroomId int64) { 224 | om.Lock() 225 | defer om.Unlock() 226 | 227 | liveroom, ok := om.liveMap[liveroomId] 228 | if !ok { 229 | logger.Warn("StopPlayStream : not found liveroomid=", liveroomId) 230 | return 231 | } 232 | 233 | if liveroom.playUserCount > 0 { 234 | liveroom.playUserCount-- 235 | DBUpdateOnlineLiveRoom(liveroom.liveRoomId, liveroom.playUserCount) 236 | } 237 | logger.Info("StopPlayStream : liveroomid=", liveroomId, ", playnum=", liveroom.playUserCount) 238 | } 239 | -------------------------------------------------------------------------------- /src/apiserver/service/payManager.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "gotye_protocol" 5 | 6 | "github.com/futurez/litego/logger" 7 | ) 8 | 9 | func ChargeRMB(resp *gotye_protocol.ChargeRMBResponse, req *gotye_protocol.ChargeRMBRequest) { 10 | sd, ok := SP_sessionMgr.readSession(req.SessionId) 11 | if !ok { 12 | resp.SetStatus(gotye_protocol.API_EXPIRED_SESSION_ERROR) 13 | logger.Warn("ChargeRMB : get session data failed.") 14 | return 15 | } 16 | sd.UpdateTick() 17 | 18 | if req.RMB <= 0 { 19 | resp.SetStatus(gotye_protocol.API_PARAM_ERROR) 20 | logger.Error("ChargeRMB : user=", sd.nickname, ", invalid rmb=", req.RMB) 21 | return 22 | } 23 | 24 | var err error 25 | resp.QinCoin, err = dbChargeRMB(sd.user_id, req.RMB) 26 | if err != nil { 27 | resp.SetStatus(gotye_protocol.API_CHARGE_RMB_ERROR) 28 | return 29 | } 30 | resp.SetStatus(gotye_protocol.API_SUCCESS) 31 | } 32 | 33 | func PayQinCoin(resp *gotye_protocol.PayQinCoinResponse, req *gotye_protocol.PayQinCoinRequest) { 34 | sd, ok := SP_sessionMgr.readSession(req.SessionId) 35 | if !ok { 36 | resp.SetStatus(gotye_protocol.API_EXPIRED_SESSION_ERROR) 37 | logger.Warn("PayQinCoin : get session data failed.") 38 | return 39 | } 40 | sd.UpdateTick() 41 | 42 | //get anchorUserId account user_id 43 | anchorUserId := DBGetUserIdByNickname(req.AnchorAccount) 44 | if anchorUserId == 0 { 45 | resp.SetStatus(gotye_protocol.API_USERNAME_NOT_EXISTS_ERROR) 46 | logger.Warn("PayQinCoin : not this account=", req.AnchorAccount) 47 | return 48 | } 49 | 50 | errorno := dbUpdateJiaCoin(anchorUserId, sd.user_id, req.QinCoin) 51 | switch errorno { 52 | case 0: 53 | resp.SetStatus(gotye_protocol.API_LACK_OF_BALANCE_ERROR) 54 | case 1: 55 | resp.SetStatus(gotye_protocol.API_SUCCESS) 56 | default: 57 | resp.SetStatus(gotye_protocol.API_SERVER_ERROR) 58 | } 59 | logger.Info("PayQinCoin : userid=", sd.user_id, "pay qincoin=", req.QinCoin, " to anchoruserid=", anchorUserId, "(", 60 | req.AnchorAccount, "), errorno=", errorno) 61 | } 62 | 63 | func GetPayAccount(resp *gotye_protocol.GetPayAccountResponse, req *gotye_protocol.GetPayAccountRequest) { 64 | sd, ok := SP_sessionMgr.readSession(req.SessionId) 65 | if !ok { 66 | resp.SetStatus(gotye_protocol.API_EXPIRED_SESSION_ERROR) 67 | logger.Warn("GetPayAccount : get session data failed.") 68 | return 69 | } 70 | sd.UpdateTick() 71 | 72 | db := SP_MysqlDbPool.GetDBConn() 73 | err := db.QueryRow("SELECT `qin_coin`,`jia_coin`,`level`,`xp` FROM tbl_pay_account WHERE user_id=?", sd.user_id). 74 | Scan(&resp.QinCoin, &resp.JiaCoin, &resp.Level, &resp.XP) 75 | 76 | if err != nil { 77 | logger.Error("GetPayAccount : err=", err.Error()) 78 | resp.SetStatus(gotye_protocol.API_SERVER_ERROR) 79 | return 80 | } 81 | logger.Info("GetPayAccount : suc qincoin=", resp.QinCoin, ",jiacoin=", resp.JiaCoin, ",level=", resp.Level, ",xp=", resp.XP) 82 | resp.SetStatus(gotye_protocol.API_SUCCESS) 83 | return 84 | } 85 | 86 | func dbUpdateJiaCoin(anchorUserId int64, vistorUserId int64, qinCoin int) int { 87 | db := SP_MysqlDbPool.GetDBConn() 88 | tx, err := db.Begin() 89 | if err != nil { 90 | logger.Error("dbUpdateJiaCoin : err=", err.Error()) 91 | return -1 92 | } 93 | defer tx.Commit() 94 | // defer ( 95 | //// tx.Exec("UNLOCK TABLES") 96 | 97 | // ) 98 | //// tx.Exec("LOCK TABLE tbl_pay_account WRITE") 99 | 100 | var errorno int 101 | err = tx.QueryRow("CALL pay_qin_coin(?, ?, ?)", anchorUserId, vistorUserId, qinCoin).Scan(&errorno) 102 | if err != nil { 103 | logger.Error("dbUpdateJiaCoin : CALL charge_rmb err=", err.Error()) 104 | return -1 105 | } 106 | logger.Info("dbUpdateJiaCoin : errorno=", errorno) 107 | return errorno 108 | } 109 | 110 | func dbChargeRMB(user_id int64, rmb int) (int, error) { 111 | db := SP_MysqlDbPool.GetDBConn() 112 | tx, err := db.Begin() 113 | if err != nil { 114 | logger.Error("dbChargeRMB : err=", err.Error()) 115 | return 0, err 116 | } 117 | 118 | defer tx.Commit() 119 | /* ( 120 | //tx.Exec("UNLOCK TABLES") 121 | 122 | )*/ 123 | 124 | //tx.Exec("LOCK TABLE tbl_pay_account WRITE") 125 | 126 | var total_qin_coin int 127 | err = tx.QueryRow("CALL charge_rmb(?, ?)", user_id, rmb).Scan(&total_qin_coin) 128 | if err != nil { 129 | logger.Error("dbChargeRMB : CALL charge_rmb err=", err.Error()) 130 | return 0, err 131 | } 132 | logger.Info("dbChargeRMB : user_id=", user_id, ", rmb=", rmb) 133 | return total_qin_coin, nil 134 | } 135 | -------------------------------------------------------------------------------- /src/apiserver/service/payManager_test.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "sync" 5 | // "gotye_protocol" 6 | "testing" 7 | ) 8 | 9 | func TestDBChargeRMB(t *testing.T) { 10 | InitMysqlDbPool("192.168.1.10", "gotye_open_live", "appuser", "gotye2013") 11 | 12 | var wait sync.WaitGroup 13 | 14 | for i := 0; i < 20; i++ { 15 | wait.Add(1) 16 | go func(n int) { 17 | defer wait.Done() 18 | qin_coin, err := dbChargeRMB(5, 1000) 19 | if err != nil { 20 | t.Error("TestdbChargeRMB = ", err.Error()) 21 | return 22 | } 23 | t.Log("n=", n, ": userid=5 pay 1000rmb, total_qin_coin=", qin_coin) 24 | }(i) 25 | } 26 | wait.Wait() 27 | } 28 | 29 | func TestDBUpdateJiaCoin(t *testing.T) { 30 | InitMysqlDbPool("192.168.1.10", "gotye_open_live", "appuser", "gotye2013") 31 | 32 | var wait sync.WaitGroup 33 | 34 | for i := 0; i < 20; i++ { 35 | wait.Add(1) 36 | go func(n int) { 37 | defer wait.Done() 38 | errno := dbUpdateJiaCoin(90, 5, 1000) 39 | if errno == -1 { 40 | t.Error("TestDBUpdateJiaCoin = ", errno) 41 | return 42 | } 43 | t.Log("n=", n, ": userid=5 pay 1000qincoin to userid=90, errno=", errno) 44 | }(i) 45 | } 46 | wait.Wait() 47 | } 48 | -------------------------------------------------------------------------------- /src/apiserver/service/refreshPlayUrls.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "gotye_protocol" 5 | "gotye_protocol/gotye_sdk" 6 | 7 | "github.com/futurez/litego/logger" 8 | ) 9 | 10 | func RefreshPlayUrls() int { 11 | liveroomIds := DBGetLiveroomIds() 12 | 13 | total := len(liveroomIds) 14 | if total <= 0 { 15 | return gotye_protocol.API_SUCCESS 16 | } 17 | 18 | limit := (total + PreRefreshNum) / PreRefreshNum * PreRefreshNum 19 | logger.Debug("RefreshPlayUrls : total=", total, ",limit=", limit) 20 | 21 | for i := 0; i < limit; i += PreRefreshNum { 22 | var ids []int64 23 | if i != (limit - PreRefreshNum) { 24 | ids = liveroomIds[i : i+PreRefreshNum] 25 | logger.Debug("RefreshPlayUrls : last i=", i, ",ids=", ids) 26 | } else { 27 | ids = liveroomIds[i:total] 28 | logger.Debug("RefreshPlayUrls : pre i=", i, ",ids=", ids) 29 | } 30 | 31 | resp, err := GotyeGetRoomsLiveInfo(ids...) 32 | if err != nil { 33 | logger.Error("UpdateNum : GotyeGetLiveContext Failed, ", err.Error()) 34 | continue 35 | } 36 | 37 | if resp.Status != gotye_sdk.API_SUCCESS { 38 | logger.Error("UpdateNum : GotyeGetLiveContext status=", resp.Status) 39 | continue 40 | } 41 | 42 | for _, entity := range resp.Entities { 43 | DBUpdateLiveroomUrls(entity.RoomId, entity.PlayRtmpUrls[0], entity.PlayHlsUrls[0], entity.PlayFlvUrls[0]) 44 | } 45 | } 46 | return gotye_protocol.API_SUCCESS 47 | } 48 | -------------------------------------------------------------------------------- /src/apiserver/service/sessionManager.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "sync" 5 | "time" 6 | 7 | "github.com/futurez/litego/logger" 8 | "github.com/futurez/litego/util" 9 | ) 10 | 11 | const ( 12 | HeartBeatTimeOut = time.Hour 13 | PreCheckSessionId = time.Minute 14 | ) 15 | 16 | type sessionManager struct { 17 | mux sync.RWMutex 18 | sessionMap map[string]*sessionData 19 | } 20 | 21 | var SP_sessionMgr = &sessionManager{sessionMap: make(map[string]*sessionData)} 22 | 23 | func init() { 24 | time.AfterFunc(PreCheckSessionId, func() { SP_sessionMgr.GC() }) 25 | } 26 | 27 | func (sm *sessionManager) GC() { 28 | sm.mux.Lock() 29 | defer sm.mux.Unlock() 30 | 31 | delIdList := make([]string, 0, len(sm.sessionMap)) 32 | now := time.Now() 33 | for id, session := range sm.sessionMap { 34 | if now.Sub(session.tick) > HeartBeatTimeOut { 35 | delIdList = append(delIdList, id) 36 | } 37 | } 38 | 39 | for _, id := range delIdList { 40 | logger.Debug("GC : Overdue sessionid = ", id) 41 | delete(sm.sessionMap, id) 42 | } 43 | time.AfterFunc(PreCheckSessionId, func() { SP_sessionMgr.GC() }) 44 | } 45 | 46 | func (sm *sessionManager) addSession(userid, liveroomid int64, nickName string) string { 47 | sm.mux.Lock() 48 | defer sm.mux.Unlock() 49 | 50 | sd := &sessionData{ 51 | session_id: util.UUID(), 52 | user_id: userid, 53 | liveroom_id: liveroomid, 54 | nickname: nickName, 55 | tick: time.Now(), 56 | bfcousOnline: true, 57 | } 58 | sm.sessionMap[sd.session_id] = sd 59 | logger.Info("addSession : session_id=", sd.session_id, ",user_id=", sd.user_id, 60 | ",liveroom_id=", sd.liveroom_id) 61 | return sd.session_id 62 | } 63 | 64 | func (sm *sessionManager) deleteSession(session_id string) { 65 | sm.mux.Lock() 66 | defer sm.mux.Unlock() 67 | logger.Info("deleteSession : session_id=", session_id) 68 | delete(sm.sessionMap, session_id) 69 | } 70 | 71 | func (sm *sessionManager) readSession(sessionId string) (*sessionData, bool) { 72 | sm.mux.RLock() 73 | defer sm.mux.RUnlock() 74 | sd, ok := sm.sessionMap[sessionId] 75 | return sd, ok 76 | } 77 | 78 | type sessionData struct { 79 | session_id string 80 | user_id int64 81 | liveroom_id int64 82 | nickname string 83 | tick time.Time 84 | allLastId int64 85 | fcousLastId int64 86 | bfcousOnline bool 87 | } 88 | 89 | func (sd *sessionData) UpdateTick() { 90 | sd.tick = time.Now() 91 | } 92 | -------------------------------------------------------------------------------- /src/apiserver/service/user.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "encoding/base64" 5 | "gotye_protocol" 6 | 7 | "github.com/futurez/litego/logger" 8 | "github.com/futurez/litego/util" 9 | ) 10 | 11 | func UserRegister(resp *gotye_protocol.RegisterResponse, req *gotye_protocol.RegisterRequest) { 12 | if len(req.AuthCode) == 0 { 13 | logger.Warn("UserRegister : authcode is null. ") 14 | resp.SetStatus(gotye_protocol.API_AUTHCODE_ERROR) 15 | return 16 | } 17 | 18 | if !SP_phoneCode.Check(req.Phone, req.AuthCode) { 19 | logger.Warn("UserRegister : authcode is error, authcode=", req.AuthCode) 20 | resp.SetStatus(gotye_protocol.API_AUTHCODE_ERROR) 21 | return 22 | } 23 | SP_phoneCode.Delete(req.Phone) 24 | 25 | user_id := DBCreateUserAccount(req.Phone, req.Passwd) 26 | if user_id < 0 { 27 | resp.SetStatus(gotye_protocol.API_SERVER_ERROR) 28 | logger.Warn("UserRegister : create user error!") 29 | return 30 | } 31 | 32 | resp.SetStatus(gotye_protocol.API_SUCCESS) 33 | logger.Info("UserRegister : Success. phone=", req.Phone) 34 | } 35 | 36 | func UserLogin(resp *gotye_protocol.LoginResponse, req *gotye_protocol.LoginRequest) { 37 | user_id, headPicId, nickname, sex, status_code := DBCheckUserAccount(req.Account, req.Passwd) 38 | 39 | resp.SetStatus(status_code) 40 | if status_code == gotye_protocol.API_SUCCESS { 41 | resp.NickName = nickname 42 | resp.LiveRoomID = DBGetLiveroomIdByUserId(user_id) 43 | resp.HeadPicId = headPicId 44 | resp.Sex = sex 45 | 46 | //判断是否已经登录过. 47 | resp.SessionID = SP_sessionMgr.addSession(user_id, resp.LiveRoomID, resp.NickName) 48 | logger.Info("UserLogin success nickname=", resp.NickName) 49 | } else { 50 | logger.Warn("UserLogin failed. account=", req.Account, ", pwd=", req.Passwd) 51 | } 52 | } 53 | 54 | func UserInfoModify(resp *gotye_protocol.ModifyUserInfoResponse, req *gotye_protocol.ModifyUserInfoRequest) { 55 | sd, ok := SP_sessionMgr.readSession(req.SessionID) 56 | if !ok { 57 | resp.SetStatus(gotye_protocol.API_EXPIRED_SESSION_ERROR) 58 | logger.Info("UserInfoModify : get session data failed.") 59 | return 60 | } 61 | sd.UpdateTick() 62 | 63 | var err error 64 | if (req.Sex == 1 || req.Sex == 2) || len(req.Address) > 0 { 65 | if err = DBModifyUserInfo(sd.user_id, req.Sex, req.Address); err != nil { 66 | resp.SetStatus(gotye_protocol.API_SERVER_ERROR) 67 | logger.Warn("UserInfoModify : user_id=", sd.user_id, ", sex=", req.Sex, ", addr=", req.Address) 68 | return 69 | } 70 | } 71 | 72 | if len(req.NickName) > 0 { 73 | if err = DBModifyUserNickName(sd.user_id, req.NickName); err != nil { 74 | resp.SetStatus(gotye_protocol.API_USERNAME_EXISTS_ERROR) 75 | logger.Warn("UserInfoModify : user_id=", sd.user_id, ", nickname=", req.NickName) 76 | return 77 | } 78 | } 79 | logger.Info("UserInfoModify : user_id=", sd.user_id, ", nickname=", req.NickName, ", sex=", req.Sex, ", address=", req.Address) 80 | resp.SetStatus(gotye_protocol.API_SUCCESS) 81 | } 82 | 83 | func UserHeadPicModify(resp *gotye_protocol.ModifyUserHeadPicResponse, req *gotye_protocol.ModifyUserHeadPicRequest) { 84 | sd, ok := SP_sessionMgr.readSession(req.SessionID) 85 | if !ok { 86 | resp.SetStatus(gotye_protocol.API_EXPIRED_SESSION_ERROR) 87 | logger.Info("UserHeadPicModify : get session data failed.") 88 | return 89 | } 90 | sd.UpdateTick() 91 | 92 | logger.Debug("UserHeadPicModify : headPicLen=", len(req.HeadPic)) 93 | headPic, err := base64.StdEncoding.DecodeString(req.HeadPic) 94 | if err != nil { 95 | resp.SetStatus(gotye_protocol.API_DECODE_HEAD_PIC_ERROR) 96 | logger.Info("UserHeadPicModify : decode err =", err.Error()) 97 | return 98 | } 99 | 100 | resp.HeadPicId, err = DBModifyUserHeadPic(sd.user_id, headPic) 101 | if err != nil { 102 | resp.SetStatus(gotye_protocol.API_SERVER_ERROR) 103 | logger.Info("UserHeadPicModify : update err = ", err) 104 | return 105 | } 106 | resp.SetStatus(gotye_protocol.API_SUCCESS) 107 | } 108 | 109 | func GetHeadPicById(id int64) ([]byte, error) { 110 | logger.Info("GetHeadPicById : id=", id) 111 | return DBGetUserHeadPic(id) 112 | } 113 | 114 | func UserPwdModify(resp *gotye_protocol.ModifyUserPwdResponse, req *gotye_protocol.ModifyUserPwdRequest) { 115 | if !util.CheckPhone(req.Phone) { 116 | resp.SetFormatStatus(gotye_protocol.API_PARAM_ERROR, "invalid phone.") 117 | logger.Warn("UserPwdModify : invalid phone=", req.Phone) 118 | return 119 | } 120 | err := DBModifyUserPwd(req.Phone, req.Passwd) 121 | if err != nil { 122 | resp.SetStatus(gotye_protocol.API_PHONE_NOT_EXISTS_ERROR) 123 | } else { 124 | resp.SetStatus(gotye_protocol.API_SUCCESS) 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/gotye_protocol/api.go: -------------------------------------------------------------------------------- 1 | package gotye_protocol 2 | 3 | //http://127.0.0.1:8080/live/login 4 | 5 | //api : /live/Login 6 | /* 7 | { 8 | "account" : "zhangsan"/"13512324432", 9 | "password": "123456" 10 | } 11 | */ 12 | type LoginRequest struct { 13 | Account string `json:"account"` 14 | Passwd string `json:"password"` 15 | } 16 | 17 | /* 18 | { 19 | "access" : "/live/Login" 20 | "status" : 21 | "desc" : 22 | "account" : "zhangsan" 23 | "nickName" : "aaaaaa" 24 | "liveRoomId" : //如果这个用户有liveRoomId,就返回,如果没有返回0 25 | "sessionId": "sasassasaasasasasas" (32个字节的字符串) 26 | } 27 | */ 28 | type LoginResponse struct { 29 | ApiResponse 30 | NickName string `json:"nickName"` 31 | LiveRoomID int64 `json:"liveRoomId"` 32 | SessionID string `json:"sessionId"` 33 | HeadPicId int64 `json:"headPicId"` 34 | Sex int8 `json:"sex"` //1:male, 2: female 35 | } 36 | 37 | //api : /live/AuthCode 38 | /* 39 | { 40 | "phone" : "13512023289", 41 | } 42 | */ 43 | type AuthCodeRequest struct { 44 | Phone string `json:"phone"` 45 | } 46 | 47 | /* 48 | { 49 | "access" : "/live/AuthCode" 50 | "status" : 51 | "desc" : 52 | } 53 | */ 54 | type AuthCodeResponse struct { 55 | ApiResponse 56 | } 57 | 58 | //api : /live/Register 59 | /* 60 | { 61 | "phone" : "13512023289", 62 | "password" : "123456" 63 | "authCode" : "", 64 | } 65 | */ 66 | type RegisterRequest struct { 67 | Phone string `json:"phone"` 68 | Passwd string `json:"password"` 69 | AuthCode string `json:"authCode"` 70 | } 71 | 72 | /* 73 | { 74 | "access" : "/live/Register" 75 | "status" : 76 | "desc" : 77 | } 78 | */ 79 | type RegisterResponse struct { 80 | ApiResponse 81 | } 82 | 83 | //api : live/ModifyUserPwd 84 | /* 85 | { 86 | "phone" : "", 87 | "password": "123456" 88 | } 89 | */ 90 | type ModifyUserPwdRequest struct { 91 | Phone string `json:"phone"` 92 | Passwd string `json:"password"` 93 | } 94 | 95 | /* 96 | { 97 | "access" : "/live/ModifyUserPwd" 98 | } 99 | */ 100 | type ModifyUserPwdResponse struct { 101 | ApiResponse 102 | } 103 | 104 | //api : /live/ModifyUserInfo 105 | /* 106 | { 107 | "sessionId" : "asssssssssssssssssss" 108 | "nickName" : 修改用户昵称 109 | } 110 | */ 111 | type ModifyUserInfoRequest struct { 112 | SessionID string `json:"sessionId"` 113 | NickName string `json:"nickName"` 114 | Sex int8 `json:"sex"` //1:male, 2: female 115 | Address string `json:"address"` 116 | } 117 | 118 | type ModifyUserInfoResponse struct { 119 | ApiResponse 120 | } 121 | 122 | //api : /live/ModifyUserHeadPic 123 | /* 124 | { 125 | "sessionId" : "asssssssssssssssssss" 126 | "headPic" : 修改用户头像 (图片base64之后成字符串再传入) 127 | } 128 | */ 129 | type ModifyUserHeadPicRequest struct { 130 | SessionID string `json:"sessionId"` 131 | HeadPic string `json:"headPic"` 132 | } 133 | 134 | type ModifyUserHeadPicResponse struct { 135 | ApiResponse 136 | HeadPicId int64 `json:"headPicId"` 137 | } 138 | 139 | //api : /live/GetUserHeadPic 140 | type GetUserHeadPicResponse struct { 141 | ApiResponse 142 | } 143 | 144 | //api : /live/GetLiveRoomList 145 | const ( 146 | ALL_LIVE_ROOM_LIST = iota + 1 147 | FOCUS_LIVE_ROOM_LIST 148 | ) 149 | 150 | /* 151 | { 152 | "sessionId" : "asssssssssssssssssss" 153 | "type" : 1(全部), 2(关注) 154 | "refresh" : 1(刷新), 0(获取下一页) 155 | "count" : 可以填充一次性刷新几个,如果不填,默认是5个 156 | } 157 | */ 158 | type GetLiveRoomListRequest struct { 159 | SessionID string `json:"sessionId"` 160 | Type int `json:"type"` 161 | Refresh int `josn:"refresh"` 162 | Count int `json:"count"` 163 | } 164 | 165 | /* 166 | { 167 | "access" : "/live/GetLiveRoomList" 168 | "status" : 169 | "desc" : 170 | "type" : 1(全部), 2(关注) 171 | "lastId" : 这次获取到的节点 172 | "list" : [ 173 | { 174 | "liveRoomId" : 175 | "liveRoomanchorPwd": 主播密码 176 | "liveRoomUserPwd": 观看直播的用户密码 177 | "liveRoomName" : 直播室名称 178 | "liveRoomDesc" : 直播室描述 179 | "liveRoomTopic": 演讲的题目 180 | "anchorName" : 主播昵称 181 | "anchorIcon" : 主播头像 182 | "followCount" : 被关注量 183 | } 184 | ] 185 | } 186 | */ 187 | type GetAllLiveRoomListResponse struct { 188 | ApiResponse 189 | Type int `json:"Type"` 190 | List []LiveRoomInfo `json:"list"` 191 | } 192 | 193 | /* 194 | { 195 | "access" : "/live/GetLiveRoomList" 196 | "status" : 197 | "desc" : 198 | "type" : 1(全部), 2(关注) 199 | "lastId" : 这次获取到的节点 200 | "onlineList" : [ 201 | { 202 | "liveRoomId" : 203 | "liveRoomanchorPwd": 主播密码 204 | "liveRoomUserPwd": 观看直播的用户密码 205 | "liveRoomName" : 直播室名称 206 | "liveRoomDesc" : 直播室描述 207 | "liveRoomTopic": 演讲的题目 208 | "anchorName" : 主播昵称 209 | "anchorIcon" : 主播头像 210 | "followCount" : 被关注量 211 | } 212 | ], 213 | "offlineList" : [ 214 | { 215 | "liveRoomId" : 216 | "liveRoomanchorPwd": 主播密码 217 | "liveRoomUserPwd": 观看直播的用户密码 218 | "liveRoomName" : 直播室名称 219 | "liveRoomDesc" : 直播室描述 220 | "liveRoomTopic": 演讲的题目 221 | "anchorName" : 主播昵称 222 | "anchorIcon" : 主播头像 223 | "followCount" : 被关注量 224 | } 225 | ] 226 | } 227 | */ 228 | type GetFcousLiveRoomListResponse struct { 229 | ApiResponse 230 | Type int `json:"Type"` 231 | OnlineList []LiveRoomInfo `json:"onlineList"` 232 | OfflineList []LiveRoomInfo `json:"offlineList"` 233 | } 234 | 235 | type LiveRoomInfo struct { 236 | LiveRoomId int64 `json:"liveRoomId"` 237 | LiveAnchorPwd string `json:"liveRoomAnchorPwd"` //主播密码 238 | LiveUserPwd string `json:"liveRoomUserPwd"` //观看直播的用户密码 239 | LiveRoomName string `json:"liveRoomName"` 240 | LiveRoomDesc string `json:"liveRoomDesc"` 241 | LiveRoomTopic string `json:"liveRoomTopic"` 242 | AnchorName string `json:"anchorName"` 243 | HeadPicId int64 `json:"headPicId"` 244 | IsFollow int8 `json:"isFollow"` //1 : 关注, 0: 未关注 245 | FollowCount int `json:"followCount"` 246 | PlayerCount int `json:"playerCount"` 247 | PlayRtmpUrl string `json:"playRtmpUrl"` 248 | PlayHlsUrl string `json:"playHlsUrl"` 249 | PlayFlvUrl string `json:"playFlvUrl"` 250 | } 251 | 252 | //api : /live/GetMyLiveRoomId 253 | /* 254 | { 255 | "sessionId" : "" 256 | } 257 | */ 258 | type GetMyLiveRoomIdRequest struct { 259 | SessionID string `json:"sessionId"` 260 | } 261 | 262 | /* 263 | { 264 | "access" : " /live/GetMyLiveRoomId" 265 | "status" : 266 | "desc" : 267 | "LiveRoomId": 1234567 268 | } 269 | */ 270 | type GetMyLiveRoomIdResponse struct { 271 | ApiResponse 272 | LiveRoomId int64 `json:"LiveRoomId"` 273 | } 274 | 275 | //api : /live/GetMyLiveRoom 276 | /* 277 | { 278 | "sessionId" : "" 279 | } 280 | */ 281 | type GetMyLiveRoomRequest struct { 282 | SessionID string `json:"sessionId"` 283 | } 284 | 285 | /* 286 | { 287 | "access" : " /live/GetMyLiveRoom" 288 | "status" : 289 | "desc" : 290 | "liveRoomId" : 291 | "liveRoomanchorPwd": 主播密码 292 | "liveRoomUserPwd": 观看直播的用户密码 293 | "liveRoomName" : 直播室名称 294 | "liveRoomDesc" : 直播室描述 295 | "liveRoomTopic": 演讲的题目 296 | "anchorName" : 主播昵称 297 | "anchorIcon" : 主播头像 298 | "followCount" : 被关注量 299 | 300 | } 301 | */ 302 | type GetMyLiveRoomResponse struct { 303 | ApiResponse 304 | LiveRoomInfo 305 | } 306 | 307 | //api : /live/ModifyMyLiveRoom 308 | /* 309 | { 310 | "sessionId" : 311 | "liveRoomId" : 可为0, 312 | "liveRoomAnchorPwd" : 主播密码 313 | "liveRoomUserPwd" : 观看直播的用户密码 314 | "liveRoomName" : 315 | "liveRoomDesc" : 316 | "liveRoomTopic" : 317 | } 318 | */ 319 | type ModifyMyLiveRoomRequest struct { 320 | SessionID string `json:"sessionId"` 321 | LiveRoomID int64 `json:"liveRoomId"` //可为0, 322 | LiveRoomAnchorPwd string `json:"liveRoomAnchorPwd"` //主播密码 323 | LiveUserPwd string `json:"liveRoomUserPwd"` //观看直播的用户密码 324 | LiveRoomName string `json:"liveRoomName"` 325 | LiveRoomDesc string `json:"liveRoomDesc"` 326 | LiveRoomTopic string `json:"liveRoomTopic"` 327 | } 328 | 329 | /* 330 | { 331 | "access" : " /live/ModifyMyLiveRoom" 332 | "status" : 333 | } 334 | */ 335 | type ModifyMyLiveRoomResponse struct { 336 | ApiResponse 337 | } 338 | 339 | //api : /live/CreateLiveRoom 340 | /* 341 | { 342 | "sessionId" : 343 | "liveRoomAnchorPwd" : 主播密码 344 | "liveRoomAssistPwd" : 助理密码 345 | "liveRoomUserPwd" : 观看密码 346 | "liveRoomName" : 直播室名称 347 | "liveRoomDesc" : 可不填 348 | "liveRoomTopic" : 可不填 349 | 350 | } 351 | */ 352 | type CreateLiveRoomRequest struct { 353 | SessionID string `json:"sessionId"` 354 | LiveAnchorPwd string `json:"liveRoomAnchorPwd"` //主播密码 355 | LiveAssistPwd string `json:"liveRoomAssistPwd"` //助理密码 356 | LiveUserPwd string `json:"liveRoomUserPwd"` //观看密码 357 | LiveRoomName string `json:"liveRoomName"` 358 | LiveRoomDesc string `json:"liveRoomDesc"` 359 | LiveRoomTopic string `json:"liveRoomTopic"` 360 | } 361 | 362 | /* 363 | { 364 | "access" : " /live/CreateLiveRoom" 365 | "status" : 366 | "liveRoomId": 367 | } 368 | */ 369 | type CreateLiveRoomResponse struct { 370 | ApiResponse 371 | LiveRoomId int64 `json:"liveRoomId"` 372 | } 373 | 374 | //api : /live/FollowLiveRoom 375 | /* 376 | { 377 | "sessionId" : 378 | "liveRoomId" : 379 | "isFollow" : 1 关注, 0 取消 380 | 381 | } 382 | */ 383 | type FollowLiveRoomRequest struct { 384 | SessionId string `json:"sessionId"` 385 | LiveRoomId int64 `json:"liveRoomId"` 386 | IsFollow int `json:"isFollow"` 387 | } 388 | 389 | /* 390 | { 391 | "access" : " /live/CreateLiveRoom" 392 | "status" : 393 | "desc" : 394 | } 395 | */ 396 | type FollowLiveRoomResponse struct { 397 | ApiResponse 398 | } 399 | 400 | //api : /live/PushLiveStream 401 | /* 402 | { 403 | "sessionId" : 404 | "liveRoomId" : 405 | "status" : // 1. push, 0. stop 406 | "timeout" : //超时时间,默认60秒. 如果在此时间内没有设置状态为1,直播状态变为0 407 | } 408 | */ 409 | type PushLiveStreamRequest struct { 410 | SessionId string `json:"sessionId"` 411 | LiveRoomId int64 `json:"liveRoomId"` 412 | Status int `json:"status"` // 1. push, 0. stop 413 | Timeout int `json:"timeout"` //超时时间,默认60秒. 如果在此时间内没有设置状态为1,直播状态变为0 414 | } 415 | 416 | /* 417 | { 418 | "access" : " /live/PushLiveStream" 419 | "status" : 420 | "desc" 421 | } 422 | */ 423 | type PushLiveStreamResponse struct { 424 | ApiResponse 425 | } 426 | 427 | /* 428 | api : /live/PlayLiveStream 429 | { 430 | "sessionId" : 431 | "liveroomId" : 432 | "status" : 433 | } 434 | */ 435 | type PlayLiveStreamRequest struct { 436 | SessionId string `json:"sessionId"` 437 | LiveroomId int64 `json:"liveroomId"` 438 | Status int `json:"status"` //1. start, 0, stop 439 | } 440 | 441 | type PlayLiveStreamResponse struct { 442 | ApiResponse 443 | } 444 | 445 | /* 446 | api : /live/GetLiveroomNumber 447 | */ 448 | type GetLiveroomNumberRequest struct { 449 | SessionId string `json:"sessionId"` 450 | LiveroomId int64 `json:"liveroomId"` 451 | } 452 | 453 | type GetLiveroomNumberResponse struct { 454 | ApiResponse 455 | LiveroomId int64 `json:"liveroomId"` 456 | Number int `json:"number"` 457 | } 458 | 459 | //api : /live/SearchLiveStream 460 | type SearchLiveStreamRequest struct { 461 | SessionId string `json:"sessionId"` 462 | Keyword string `json:"keyword"` 463 | } 464 | 465 | type SearchLiveStreamResponse struct { 466 | ApiResponse 467 | LiveRoomInfo 468 | IsPlay int8 `json:"isPlay"` //1 : 直播, 0: 未直播 469 | } 470 | 471 | //api : /live/GetAdLiveRoom 472 | type GetAdLiveRoomListRequest struct { 473 | SessionId string `json:"sessionId"` 474 | } 475 | 476 | type GetAdLiveRoomListResponse struct { 477 | ApiResponse 478 | LiveRoomInfo 479 | } 480 | 481 | /* 482 | api : /pay/ChargeRMB 483 | */ 484 | type ChargeRMBRequest struct { 485 | SessionId string `json:"sessionId"` 486 | RMB int `json:"rmb"` 487 | } 488 | 489 | type ChargeRMBResponse struct { 490 | ApiResponse 491 | QinCoin int `json:"qinCoin"` 492 | } 493 | 494 | /* 495 | api : /pay/PayQinCoin 496 | */ 497 | type PayQinCoinRequest struct { 498 | SessionId string `json:"sessionId"` 499 | QinCoin int `json:"qinCoin"` //支付亲元 500 | AnchorAccount string `json:"anchorAccount"` 501 | } 502 | 503 | type PayQinCoinResponse struct { 504 | ApiResponse 505 | QinCoin int `json:"qinCoin"` //剩余多少亲元 506 | } 507 | 508 | /* 509 | api : /pay/GetPayAccount 510 | */ 511 | type GetPayAccountRequest struct { 512 | SessionId string `json:"sessionId"` 513 | } 514 | 515 | type GetPayAccountResponse struct { 516 | ApiResponse 517 | QinCoin int `json:"qinCoin"` //剩余亲元 518 | JiaCoin int `json:"jiaCoin"` //收入加元 519 | Level int `json:"level"` //用户等级 520 | XP int `json:"xp"` //用户经验值 521 | } 522 | -------------------------------------------------------------------------------- /src/gotye_protocol/api_doc.md: -------------------------------------------------------------------------------- 1 | response status code : 2 | //common 3 | API_SUCCESS = 10000 4 | API_SERVER_ERROR = 10001 5 | API_PARAM_ERROR = 10002 6 | API_EXPIRED_SESSION_ID_ERROR = 10004 //sessionid过期,这时应该重新申请 7 | API_LIVEROOM_NOT_EXISTS_ERROR = 10005 8 | 9 | // api : /live/Login 10 | API_ACCOUNT_NOT_EXISTS_ERROR = 10100 11 | API_LOGIN_PASSWORD_ERROR = 10101 12 | 13 | // api : /live/Register 14 | API_ACCOUNT_EXISTS_ERROR = 10200 //账号已经存在 15 | API_PHONE_EXISTS_ERROR = 10201 //手机号已经存在 16 | API_EMAIL_EXISTS_ERROR = 10202 //邮箱已经存在 17 | 18 | // api : /live/GetLiveRoomList 19 | API_NOT_PUBLISHING_LIVEROOM_ERROR = 10300 //当前没有正在直播的用户 20 | API_NOT_FOLLOW_LIVEROOM_ERROR = 10301 //如果你没有关注任何直播用户 21 | 22 | 23 | 24 | 以下API都是POST method 25 | 26 | api : /live/Login 27 | request: 28 | { 29 | "account" : "账号/邮箱/手机号码", 30 | "password": "123456" 31 | } 32 | 33 | response: 34 | { 35 | "access" : "/live/Login" 36 | "status" : 37 | "desc" : 38 | "account" : "zhangsan" 39 | "nickName" : "aaaaaa" 40 | "liveRoomId" : //如果这个用户有liveRoomId,就返回,如果没有返回0 41 | "sessionId": "sasassasaasasasasas" (32个字节的字符串) 42 | } 43 | 44 | api : /live/Register 45 | request: 46 | { 47 | "username" : "zhangsan", 48 | "phone" : "13512023289", 49 | "email" : "example@gotye.com.cn" 50 | "password" : "123456" 51 | } 52 | 53 | response: 54 | { 55 | "access" : "/live/Register" 56 | "status" : 57 | "desc" : 58 | "account" : "zhangsan" 59 | "nickName" : "zhangsan" //刚注册成功的,nickName等于account 60 | "sessionId": "sasassasaasasasasas" (32个字节的字符串) 61 | } 62 | 63 | api : /live/modifyUserInfo 64 | request: 65 | { 66 | "sessionId" : "asssssssssssssssssss" 67 | "nickName" : 修改用户昵称,如果不修改传"" 68 | "userIcon" : 修改用户头像,如果不修改传"" 69 | } 70 | 71 | response: 72 | { 73 | "access" : "/live/Register" 74 | "status" : 75 | "desc" : 76 | } 77 | 78 | api : /live/GetLiveRoomList 79 | request 80 | { 81 | "sessionId" : "asssssssssssssssssss" 82 | "liveRoomType" : 1(全部), 2(关注) 83 | "index" : 从哪一个开始获取,第一次获取填0,下一次填充服务器返回值 84 | "count" : 可以填充一次性刷新几个,如果不填,默认是5个 85 | } 86 | 87 | response 88 | { 89 | "access" : "/live/GetLiveRoomList" 90 | "status" : 91 | "desc" : 92 | "liveRoomType" : 1(全部), 2(关注) 93 | "index" : 5 //获取到的位置,用于下一次获取的index 94 | "count" : 获取了几个 95 | "total" : 123 //如果已经获得的LiveRoom已经等于Total,就代表已经获取结束。 96 | "list" : [ 97 | { 98 | "liveRoomId" : 99 | "liveRoomanchorPwd": 主播密码 100 | "liveRoomUserPwd": 观看直播的用户密码 101 | "liveRoomName" : 直播室名称 102 | "liveRoomDesc" : 直播室描述 103 | "liveRoomTopic": 演讲的题目 104 | "anchorName" : 主播昵称 105 | "anchorIcon" : 主播头像 106 | "followCount" : 被关注量 107 | } 108 | ] 109 | } 110 | 111 | api : /live/GetMyLiveRoomId 112 | request: 113 | { 114 | "sessionId" : "" 115 | } 116 | 117 | response 118 | { 119 | "access" : " /live/GetMyLiveRoomId" 120 | "status" : API_LIVEROOM_NOT_EXISTS_ERROR 121 | "desc" : 122 | "LiveRoomId": 1234567 123 | } 124 | 125 | api : /live/GetMyLiveRoom 126 | request : 127 | { 128 | "sessionId" : "" 129 | } 130 | 131 | response : 132 | { 133 | "access" : " /live/GetMyLiveRoom" 134 | "status" : API_LIVEROOM_NOT_EXISTS_ERROR 135 | "desc" : 136 | "liveRoomId" : 137 | "liveRoomanchorPwd": 主播密码 138 | "liveRoomUserPwd": 观看直播的用户密码 139 | "liveRoomName" : 直播室名称 140 | "liveRoomDesc" : 直播室描述 141 | "liveRoomTopic": 演讲的题目 142 | "anchorName" : 主播昵称 143 | "anchorIcon" : 主播头像 144 | "focusCount" : 被关注量 145 | 146 | } 147 | 148 | 149 | 150 | api : /live/ModifyMyLiveRoom 151 | request: 152 | { 153 | "sessionId" : 154 | "liveRoomId" : 可为0, 155 | "liveRoomAnchorPwd" : 主播密码 156 | "liveRoomUserPwd" : 观看直播的用户密码 157 | "liveRoomName" : 158 | "liveRoomDesc" : 159 | "liveRoomTopic" : 160 | } 161 | 162 | response: 163 | { 164 | "access" : " /live/ModifyMyLiveRoom" 165 | "status" : API_LIVEROOM_NOT_EXISTS_ERROR 166 | "desc" : 167 | } 168 | 169 | api : /live/CreateLiveRoom 170 | request: 171 | { 172 | "sessionId" : 173 | "liveRoomanchorPwd" : 主播密码 174 | "liveRoomUserPwd" : 观看直播的用户密码 175 | "liveRoomName" : 直播室名称 176 | "liveRoomDesc" : 可不填 177 | "liveRoomTopic" : 可不填 178 | 179 | } 180 | 181 | response: 182 | { 183 | "access" : " /live/CreateLiveRoom" 184 | "status" : API_SERVER_ERROR / API_PARAM_ERROR 185 | "liveRoomId": 186 | } 187 | 188 | api : /live/FollowLiveRoom 189 | request: 190 | { 191 | "sessionId" : 192 | "liveRoomId" : 193 | "isFollow" : 1 关注, 0 取消 194 | 195 | } 196 | 197 | response 198 | { 199 | "access" : " /live/CreateLiveRoom" 200 | "status" : 201 | "desc" 202 | } 203 | 204 | 205 | api : /live/PushLiveStream 206 | request: 207 | { 208 | "sessionId" : 209 | "liveRoomId" : 210 | "status" : 1在推流, 0停止推流 211 | "timeout" : 超时时间,默认60秒. 如果在此时间内没有设置状态为1,直播状态变为0 212 | } 213 | 214 | response: 215 | { 216 | "access" : " /live/PushLiveStream" 217 | "status" : 218 | "desc" 219 | } 220 | -------------------------------------------------------------------------------- /src/gotye_protocol/base.go: -------------------------------------------------------------------------------- 1 | package gotye_protocol 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | //All API respone must inherit this struct. 8 | type ApiResponse struct { 9 | Access string `json:"access"` 10 | Status int `json:"status"` 11 | Desc string `json:"desc"` 12 | } 13 | 14 | func (r *ApiResponse) SetAccess(access string) { 15 | r.Access = access 16 | } 17 | 18 | func (r *ApiResponse) SetStatus(status int) { 19 | r.Status = status 20 | r.Desc = ApiStatus[r.Status] 21 | } 22 | 23 | func (r *ApiResponse) SetFormatStatus(status int, val string) { 24 | r.Status = status 25 | r.Desc = fmt.Sprintf("%s", val) 26 | } 27 | -------------------------------------------------------------------------------- /src/gotye_protocol/gotye_sdk/api.go: -------------------------------------------------------------------------------- 1 | // api.go 2 | package gotye_sdk 3 | 4 | var ( 5 | HttpDomain = "https://livevip.com.cn/liveApi/" 6 | HttpUrlAccessToken = HttpDomain + "AccessToken" 7 | HttpUrlCreateRoom = HttpDomain + "CreateRoom" 8 | HttpUrlModifyRoom = HttpDomain + "ModifyRoom" 9 | HttpGetLiveContext = HttpDomain + "GetLiveContext" 10 | HttpGetRoomsLiveInfo = HttpDomain + "GetRoomsLiveInfo" 11 | ) 12 | 13 | type AccessTokenAppRequest struct { 14 | Scope string `json:"scope"` //scope = "app" 15 | UserName string `json:"username"` //developer account 16 | Password string `json:"password"` //developer password 17 | } 18 | 19 | type AccessTokenRoomRequest struct { 20 | Scope string `json:"scope"` //scope = "room" 21 | RoomId int64 `json:"roomId"` //liveroom_id 22 | Password string `json:"password"` //liveroom password 23 | SecretKey string `json:"secretKey"` //md5(roomId+password+accessSecret) 24 | NickName string `json:"nickName"` // 25 | } 26 | 27 | type AccessTokenResponse struct { 28 | ExpiresIn int64 `json:"expiresIn"` //有效时间,单位(秒) 29 | AccessToken string `json:"accessToken"` //返回的token 30 | Role int `json:"role"` //角色: 1-后台用户, 2-主播端, 3-助理, 4-观众 31 | } 32 | 33 | type ApiResponse struct { 34 | AccessPath string `json:"accessPath"` 35 | Runtime int `json:"runtime"` 36 | Systime int64 `json:"systime"` 37 | Status int `json:"status"` 38 | } 39 | 40 | type CreateRoomRequest struct { 41 | RoomName string `json:"roomName"` 42 | AnchorPwd string `json:"anchorPwd"` //主播登录密码 43 | AssistPwd string `json:"assistPwd"` //助理登录密码 44 | UserPwd string `json:"userPwd"` //用户登录密码 45 | AnchorDesc string `json:"anchorDesc"` //"主播描述" 46 | ContentDesc string `json:"contentDesc"` //"内容描述" 47 | ThirdRoomId int64 `json:"thirdRoomID"` //是否用第三方roomID 48 | } 49 | 50 | type CreateRoomResponse struct { 51 | ApiResponse 52 | Entity CreateRoomEntity `json:"entity"` 53 | } 54 | 55 | type CreateRoomEntity struct { 56 | RoomId int64 `json:"roomId"` //live room id 57 | AppUserId int `json:"appUserId"` //app id 58 | RoomName string `json:"roomName"` //主播室名称 59 | AnchorPwd string `json:"anchorPwd"` //主播密码 60 | UserPwd string `json:"userPwd"` //观众密码 61 | AssistPwd string `json:"assistPwd"` //助理密码 62 | AnchorDesc string `json:"anchorDesc"` //主播室描述 63 | ContentDesc string `json:"contentDesc"` //演讲主题 64 | DateCreate int64 `json:"dateCreate"` //创建时间 65 | ThirdRoomId int64 `json:"thirdRoomId"` 66 | } 67 | 68 | type ModifyRoomRequest struct { 69 | RoomId int64 `json:"roomId"` 70 | RoomName string `json:"roomName"` 71 | EnableRecordFlag int `json:"enableRecordFlag"` 72 | PermanentPlayFlag int `json:"permanentPlayFlag"` 73 | StartPlayTime int `json:"startPlayTime"` 74 | AnchorPwd string `json:"anchorPwd"` 75 | AssistPwd string `json:"assistPwd"` 76 | UserPwd string `json:"userPwd"` 77 | AnchorDesc string `json:"anchorDesc"` 78 | ContentDesc string `json:"contentDesc"` 79 | } 80 | 81 | type ModifyRoomResponse struct { 82 | ApiResponse 83 | AffectedRows int `json:"affectedRows"` 84 | } 85 | 86 | type GetLiveContextRequest struct { 87 | RoomId int64 `json:"roomId"` 88 | } 89 | 90 | type GetLiveContextResponse struct { 91 | ApiResponse 92 | Entity LiveContext `json:"entity"` 93 | } 94 | 95 | type LiveContext struct { 96 | RecordingStatus int `json:"recordingStatus"` 97 | PlayUserCount int `josn:"playUserCount"` 98 | } 99 | 100 | type GetRoomsLiveInfoRequest struct { 101 | RoomIds []int64 `json:"roomIds"` 102 | } 103 | 104 | type GetRoomsLiveInfoResponse struct { 105 | ApiResponse 106 | Entities []LiveRoomInfo `json:"entities"` 107 | } 108 | 109 | type LiveRoomInfo struct { 110 | RoomId int64 `json:"roomId"` 111 | PlayUserCount int `json:"playUserCount"` 112 | StreamStatus int `json:"streamStatus"` 113 | PlayRtmpUrls []string `json:"playRtmpUrls"` 114 | PlayHlsUrls []string `json:"playHlsUrls"` 115 | PlayFlvUrls []string `json:"playFlvUrls"` 116 | } 117 | -------------------------------------------------------------------------------- /src/gotye_protocol/gotye_sdk/status_code.go: -------------------------------------------------------------------------------- 1 | package gotye_sdk 2 | 3 | const ( 4 | //system 5 | API_SUCCESS = 200 6 | API_INVALID_TOKEN_ERROR = 401 //认证失败,无效token 7 | API_INVALID_LICENSE_ERROR = 411 //无效许可 8 | API_NO_PERMISSION_ACCESS_ERROR = 420 //没有权限访问此资源 9 | API_SYSTEM_ERROR = 500 //系统处理异常 10 | 11 | //live room 12 | API_INVALID_LIVEROOM_ID_ERROR = 2001 //无效的主播室ID 13 | API_NOT_EXISTS_LIVEROOM_ID_ERROR = 2002 //主播室不存在 14 | API_REPECT_PASSWORD_LIVEROOM_ERROR = 2003 //主播室密码 15 | API_INVALID_PASSWORD_LIVEROOM_ERROR = 2004 //主播室密码非法 16 | API_INVALID_LIVEROOM_NAME_ERROR = 2005 //主播室名称非法 17 | API_NULL_LIVEROOM_ID_ERROR = 2007 //主播室ID为空 18 | API_EXISTS_THIRD_LIVEROOM_ID_ERROR = 2008 //thirdRoomId已经存在 19 | 20 | //app 21 | API_APP_ACCOUNT_OVERDUE_ERROR = 3001 //APP账号已过期 22 | API_STOP_APP_SERVICE_ERROR = 3003 //暂停服务 23 | 24 | //attachment 25 | API_REPECT_ATTACHMENT_ERROR = 4001 //附件重复 26 | ) 27 | 28 | // 29 | var HttpHeaders = map[string]string{ 30 | "Accept": "application/json", 31 | "Content-Type": "application/json", 32 | "Authorization": "", //验证token 33 | } 34 | 35 | //通用调用参数: 36 | 37 | //index //索引, 默认0 38 | //count //数量, 默认10,最大100 39 | //通用返回值: 40 | 41 | //accessPath //访问接口路径 42 | //runtime //接口执行时间 43 | //systime //服务器调用时间戳 44 | //affectedRows //受影响的行,一般添加或修改时会返回 45 | //status //状态码 46 | //errorDesc //错误详细信息 47 | -------------------------------------------------------------------------------- /src/gotye_protocol/status_code.go: -------------------------------------------------------------------------------- 1 | package gotye_protocol 2 | 3 | const ( 4 | //common 5 | API_SUCCESS = 10000 6 | API_SERVER_ERROR = 10001 7 | API_PARAM_ERROR = 10002 8 | API_EXPIRED_SESSION_ERROR = 10003 9 | 10 | //account 11 | API_USERNAME_NOT_EXISTS_ERROR = 10100 12 | API_USERNAME_EXISTS_ERROR = 10101 13 | API_LOGIN_PASSWORD_ERROR = 10102 14 | API_PHONE_EXISTS_ERROR = 10103 15 | API_PHONE_NOT_EXISTS_ERROR = 10104 16 | API_AUTHCODE_ERROR = 10105 17 | 18 | //liveroom 19 | API_LIVEROOM_ID_NOT_EXIST_ERROR = 10200 20 | API_REPECT_PASSWORD_LIVEROOM_ERROR = 10201 21 | API_LIVEROOM_NOT_EXISTS_ERROR = 10202 22 | API_INVALID_LIVEROOM_NAME_ERROR = 10203 23 | API_INVALID_PASSWORD_LIVEROOM_ERROR = 10204 24 | 25 | //picture 26 | API_DECODE_HEAD_PIC_ERROR = 10300 27 | 28 | //pay 29 | API_CHARGE_RMB_ERROR = 10400 30 | API_LACK_OF_BALANCE_ERROR = 10401 31 | ) 32 | 33 | var ApiStatus = map[int]string{ 34 | API_SUCCESS: "成功", 35 | API_SERVER_ERROR: "系统异常", 36 | API_PARAM_ERROR: "参数错误", 37 | API_EXPIRED_SESSION_ERROR: "Token无效", 38 | 39 | API_USERNAME_NOT_EXISTS_ERROR: "用户名不存在", 40 | API_USERNAME_EXISTS_ERROR: "用户名已使用", 41 | API_LOGIN_PASSWORD_ERROR: "登录密码错误", 42 | API_PHONE_EXISTS_ERROR: "手机已注册", 43 | API_PHONE_NOT_EXISTS_ERROR: "手机不存在", 44 | API_AUTHCODE_ERROR: "验证码错误", 45 | 46 | API_LIVEROOM_ID_NOT_EXIST_ERROR: "直播室ID不存在", 47 | API_REPECT_PASSWORD_LIVEROOM_ERROR: "直播室密码重复", 48 | API_LIVEROOM_NOT_EXISTS_ERROR: "直播室不存在", 49 | API_INVALID_LIVEROOM_NAME_ERROR: "直播室名称非法", 50 | API_INVALID_PASSWORD_LIVEROOM_ERROR: "直播室密码非法", 51 | 52 | API_DECODE_HEAD_PIC_ERROR: "头像解码错误", 53 | 54 | API_CHARGE_RMB_ERROR: "支付系统异常", 55 | API_LACK_OF_BALANCE_ERROR: "账户余额不足", 56 | } 57 | --------------------------------------------------------------------------------