importer/kmedia/holidays.go
package kmedia
import (
"encoding/json"
"time"
log "github.com/Sirupsen/logrus"
"github.com/pkg/errors"
"github.com/volatiletech/null/v8"
"github.com/volatiletech/sqlboiler/queries/qm"
"github.com/volatiletech/sqlboiler/v4/boil"
qm4 "github.com/volatiletech/sqlboiler/v4/queries/qm"
"github.com/Bnei-Baruch/mdb/api"
"github.com/Bnei-Baruch/mdb/common"
"github.com/Bnei-Baruch/mdb/hebcal"
"github.com/Bnei-Baruch/mdb/importer/kmedia/kmodels"
"github.com/Bnei-Baruch/mdb/models"
"github.com/Bnei-Baruch/mdb/utils"
)
var knownKMContentTypes = map[int]string{
1: common.CT_VIDEO_PROGRAM_CHAPTER,
4: common.CT_LESSON_PART,
5: common.CT_LECTURE,
16: common.CT_FRIENDS_GATHERING,
17: common.CT_VIRTUAL_LESSON,
18: common.CT_MEAL,
}
type HolidayCollection struct {
Holiday string
Year int
}
var HolidayCatalogs = map[int]HolidayCollection{
8208: {Holiday: hebcal.H_CHANUKAH, Year: 2001},
8210: {Holiday: hebcal.H_CHANUKAH, Year: 2002},
8211: {Holiday: hebcal.H_CHANUKAH, Year: 2003},
8212: {Holiday: hebcal.H_CHANUKAH, Year: 2004},
8213: {Holiday: hebcal.H_CHANUKAH, Year: 2005},
8214: {Holiday: hebcal.H_CHANUKAH, Year: 2006},
8215: {Holiday: hebcal.H_CHANUKAH, Year: 2007},
8216: {Holiday: hebcal.H_CHANUKAH, Year: 2008},
8217: {Holiday: hebcal.H_CHANUKAH, Year: 2009},
8218: {Holiday: hebcal.H_CHANUKAH, Year: 2010},
8219: {Holiday: hebcal.H_CHANUKAH, Year: 2011},
8220: {Holiday: hebcal.H_CHANUKAH, Year: 2012},
8224: {Holiday: hebcal.H_CHANUKAH, Year: 2013},
8225: {Holiday: hebcal.H_CHANUKAH, Year: 2014},
8226: {Holiday: hebcal.H_CHANUKAH, Year: 2015},
8227: {Holiday: hebcal.H_CHANUKAH, Year: 2016},
8246: {Holiday: hebcal.H_PESACH, Year: 2001},
8247: {Holiday: hebcal.H_PESACH, Year: 2002},
8248: {Holiday: hebcal.H_PESACH, Year: 2003},
8249: {Holiday: hebcal.H_PESACH, Year: 2004},
8250: {Holiday: hebcal.H_PESACH, Year: 2005},
8251: {Holiday: hebcal.H_PESACH, Year: 2006},
8252: {Holiday: hebcal.H_PESACH, Year: 2007},
8253: {Holiday: hebcal.H_PESACH, Year: 2008},
8254: {Holiday: hebcal.H_PESACH, Year: 2009},
8255: {Holiday: hebcal.H_PESACH, Year: 2010},
8256: {Holiday: hebcal.H_PESACH, Year: 2011},
8257: {Holiday: hebcal.H_PESACH, Year: 2012},
8258: {Holiday: hebcal.H_PESACH, Year: 2013},
8259: {Holiday: hebcal.H_PESACH, Year: 2014},
8260: {Holiday: hebcal.H_PESACH, Year: 2015},
8261: {Holiday: hebcal.H_PESACH, Year: 2016},
8262: {Holiday: hebcal.H_PESACH, Year: 2017},
8297: {Holiday: hebcal.H_PURIM, Year: 2001},
8298: {Holiday: hebcal.H_PURIM, Year: 2002},
8299: {Holiday: hebcal.H_PURIM, Year: 2003},
8300: {Holiday: hebcal.H_PURIM, Year: 2004},
8301: {Holiday: hebcal.H_PURIM, Year: 2014},
8302: {Holiday: hebcal.H_PURIM, Year: 2015},
8303: {Holiday: hebcal.H_PURIM, Year: 2016},
8304: {Holiday: hebcal.H_PURIM, Year: 2017},
8191: {Holiday: hebcal.H_ROSH_HASHANA, Year: 2002},
8190: {Holiday: hebcal.H_ROSH_HASHANA, Year: 2003},
8192: {Holiday: hebcal.H_ROSH_HASHANA, Year: 2005},
8193: {Holiday: hebcal.H_ROSH_HASHANA, Year: 2006},
8194: {Holiday: hebcal.H_ROSH_HASHANA, Year: 2007},
8195: {Holiday: hebcal.H_ROSH_HASHANA, Year: 2008},
8196: {Holiday: hebcal.H_ROSH_HASHANA, Year: 2009},
8197: {Holiday: hebcal.H_ROSH_HASHANA, Year: 2010},
8207: {Holiday: hebcal.H_ROSH_HASHANA, Year: 2011},
8198: {Holiday: hebcal.H_ROSH_HASHANA, Year: 2012},
8199: {Holiday: hebcal.H_ROSH_HASHANA, Year: 2013},
8200: {Holiday: hebcal.H_ROSH_HASHANA, Year: 2014},
8201: {Holiday: hebcal.H_ROSH_HASHANA, Year: 2015},
8202: {Holiday: hebcal.H_ROSH_HASHANA, Year: 2016},
8189: {Holiday: hebcal.H_ROSH_HASHANA, Year: 2017},
8263: {Holiday: hebcal.H_SHAVUOT, Year: 2001},
8264: {Holiday: hebcal.H_SHAVUOT, Year: 2002},
8265: {Holiday: hebcal.H_SHAVUOT, Year: 2003},
8272: {Holiday: hebcal.H_SHAVUOT, Year: 2004},
8266: {Holiday: hebcal.H_SHAVUOT, Year: 2005},
8267: {Holiday: hebcal.H_SHAVUOT, Year: 2006},
8268: {Holiday: hebcal.H_SHAVUOT, Year: 2007},
8269: {Holiday: hebcal.H_SHAVUOT, Year: 2008},
8270: {Holiday: hebcal.H_SHAVUOT, Year: 2009},
8271: {Holiday: hebcal.H_SHAVUOT, Year: 2010},
8273: {Holiday: hebcal.H_SHAVUOT, Year: 2011},
8274: {Holiday: hebcal.H_SHAVUOT, Year: 2012},
8275: {Holiday: hebcal.H_SHAVUOT, Year: 2013},
8276: {Holiday: hebcal.H_SHAVUOT, Year: 2014},
8277: {Holiday: hebcal.H_SHAVUOT, Year: 2015},
8278: {Holiday: hebcal.H_SHAVUOT, Year: 2016},
8279: {Holiday: hebcal.H_SHAVUOT, Year: 2017},
8230: {Holiday: hebcal.H_SUKKOT, Year: 2003},
8242: {Holiday: hebcal.H_SUKKOT, Year: 2004},
8232: {Holiday: hebcal.H_SUKKOT, Year: 2005},
8233: {Holiday: hebcal.H_SUKKOT, Year: 2006},
8234: {Holiday: hebcal.H_SUKKOT, Year: 2007},
8241: {Holiday: hebcal.H_SUKKOT, Year: 2008},
8235: {Holiday: hebcal.H_SUKKOT, Year: 2009},
8236: {Holiday: hebcal.H_SUKKOT, Year: 2010},
8243: {Holiday: hebcal.H_SUKKOT, Year: 2011},
8244: {Holiday: hebcal.H_SUKKOT, Year: 2012},
8237: {Holiday: hebcal.H_SUKKOT, Year: 2013},
8238: {Holiday: hebcal.H_SUKKOT, Year: 2014},
8239: {Holiday: hebcal.H_SUKKOT, Year: 2015},
8240: {Holiday: hebcal.H_SUKKOT, Year: 2016},
8228: {Holiday: hebcal.H_SUKKOT, Year: 2017},
}
var HolidayTags = map[string]string{
hebcal.H_ROSH_HASHANA: "PkEfPB9i",
hebcal.H_SUKKOT: "Q2ZFsb9a",
hebcal.H_CHANUKAH: "rxNl0zXg",
hebcal.H_PURIM: "ZjqGWdYE",
hebcal.H_PESACH: "RWqjxgkj",
hebcal.H_SHAVUOT: "MyLcuAgH",
}
func ImportHolidays() {
clock := Init()
stats = NewImportStatistics()
csMap, err := loadAndImportMissingHolidayCollections()
utils.Must(err)
utils.Must(importHolidaysContainers(csMap))
stats.dump()
Shutdown()
log.Info("Success")
log.Infof("Total run time: %s", time.Now().Sub(clock).String())
}
func loadAndImportMissingHolidayCollections() (map[int]*models.Collection, error) {
hcal := new(hebcal.Hebcal)
if err := hcal.Load(); err != nil {
return nil, errors.Wrap(err, "Load hebcal")
}
cs, err := models.Collections(
qm4.Where("type_id = ?", common.CONTENT_TYPE_REGISTRY.ByName[common.CT_HOLIDAY].ID)).
All(mdb)
if err != nil {
return nil, errors.Wrap(err, "Load collections")
}
csMap := make(map[int]*models.Collection)
for i := range cs {
c := cs[i]
if !c.Properties.Valid {
continue
}
var props map[string]interface{}
if err := json.Unmarshal(c.Properties.JSON, &props); err != nil {
return nil, errors.Wrapf(err, "json.Unmarshal collection properties %d", c.ID)
}
if kmid, ok := props["kmedia_id"]; ok {
csMap[int(kmid.(float64))] = c
}
}
for k, v := range HolidayCatalogs {
if _, ok := csMap[k]; ok {
continue
}
start, end := hcal.GetPeriod(v.Holiday, v.Year)
if start == "" || end == "" {
return nil, errors.Errorf("Holiday missing period %s %d", v.Holiday, v.Year)
}
props := map[string]interface{}{
"kmedia_id": k,
"holiday_tag": HolidayTags[v.Holiday],
"start_date": start,
"end_date": end,
}
log.Infof("Create collection %v", props)
c, err := api.CreateCollection(mdb, common.CT_HOLIDAY, props)
if err != nil {
return nil, errors.Wrapf(err, "Create collection %v", props)
}
stats.CollectionsCreated.Inc(1)
csMap[k] = c
// I18n
descriptions, err := kmodels.CatalogDescriptions(kmdb, qm.Where("catalog_id = ?", k)).All()
if err != nil {
return nil, errors.Wrapf(err, "Lookup catalog descriptions, [kmid %d]", k)
}
for _, d := range descriptions {
if d.Name.Valid && d.Name.String != "" {
ci18n := models.CollectionI18n{
CollectionID: c.ID,
Language: common.LANG_MAP[d.LangID.String],
Name: null.NewString(d.Name.String, d.Name.Valid),
}
err = ci18n.Upsert(mdb,
true,
[]string{"collection_id", "language"},
boil.Whitelist("name"),
boil.Infer())
if err != nil {
return nil, errors.Wrapf(err, "Upsert collection i18n, collection [%d]", c.ID)
}
}
}
}
return csMap, nil
}
func importHolidaysContainers(csMAp map[int]*models.Collection) error {
cnMap, cuMap, err := loadContainersInCatalogsAndCUs(12)
if err != nil {
return errors.Wrap(err, "Load containers")
}
for cnID, cn := range cnMap {
tx, err := mdb.Begin()
utils.Must(err)
// import container
cu, ok := cuMap[cnID]
if ok {
// update - for tags
cu, err = importContainer(tx, cn, nil, common.CONTENT_TYPE_REGISTRY.ByID[cu.TypeID].Name, "", 0)
if err != nil {
utils.Must(tx.Rollback())
return errors.Wrapf(err, "Import existing container %d", cnID)
}
} else {
if ct, ok := knownKMContentTypes[cn.ContentTypeID.Int]; ok {
// create - CU doesn't exist
cu, err = importContainerWOCollectionNewCU(tx, cn, ct)
if err != nil {
utils.Must(tx.Rollback())
return errors.Wrapf(err, "Import new container %d", cnID)
}
} else {
utils.Must(tx.Rollback())
continue
}
}
// create or update CCUs
for i := range cn.R.Catalogs {
catalog := cn.R.Catalogs[i]
c, ok := csMAp[catalog.ID]
if !ok {
continue
}
log.Infof("Associating %d %s to %d %s: [cu,c]=[%d,%d]", cn.ID, cn.Name.String, catalog.ID, catalog.Name, cu.ID, c.ID)
if tx == nil {
tx, err = mdb.Begin()
utils.Must(err)
}
err = createOrUpdateCCU(tx, cu, models.CollectionsContentUnit{
CollectionID: c.ID,
ContentUnitID: cu.ID,
})
if err != nil {
utils.Must(tx.Rollback())
return errors.Wrapf(err, "Create or update CCU %d", cnID)
}
}
if tx != nil {
utils.Must(tx.Commit())
}
}
return nil
}